Archived

This forum has been archived. Please start a new discussion on GitHub.

Object Factories: Java vs C#

kwaclaw
kwaclaw Oshawa, Canada
I am writing both, Java and .NET clients against the same Slice definitions of classes without methods (only data members). All works fine with .NET, but in Java I get Ice.NoObjectFactoryException errors, and I only get my client working once I add the appropriate factories. This is with ICE 3.2.1.

This seems to contradict the docs, with state (for both, java and C#) that one does not need to register an object factory for classes that only have data members.

One example of the Slice definitions I am using is:
["clr:property"]
  class State {
    string Key;
    string CountryKey;
    string Id;
    string Name;
  };
  
  sequence<State> StateSeq;

  ["clr:property"]
  class Country {
    string Key;
    string Id;
    string Name;
    StateSeq States;
  };

  sequence<Country> CountrySeq;

  ["ami", "amd"] interface CommonServices {
    ...
    idempotent OpStatus GetCountries(out CountrySeq countries)
      throws ServiceError;
    ...
  };
Calling GetCountries() throws an Ice.NoObjectFactoryException. Is this my error, a problem with the docs, or a bug in ICE for Java?

Regards,

Karl

Comments

  • mes
    mes California
    Hi Karl,

    By any chance are you specifying a Java package via metadata? If so, that can cause object unmarshaling to fail. Briefly, to unmarshal an object, the Ice run time converts an object's type id as it is sent over the wire into a classname (such as Acme::Widget into Acme.Widget) and the run time attempts to load that class dynamically. However, if you specify package metadata, the name of the Java class changes to something the Ice run time cannot predict, therefore you need to take additional action.

    See the manual for details.

    Take care,
    - Mark
  • kwaclaw
    kwaclaw Oshawa, Canada
    mes wrote: »
    Hi Karl,

    By any chance are you specifying a Java package via metadata? If so, that can cause object unmarshaling to fail. Briefly, to unmarshal an object, the Ice run time converts an object's type id as it is sent over the wire into a classname (such as Acme::Widget into Acme.Widget) and the run time attempts to load that class dynamically. However, if you specify package metadata, the name of the Java class changes to something the Ice run time cannot predict, therefore you need to take additional action.

    No, I have not added any metadata directives for Java to my Slice definitions.
    The application is a JBOSS application, if that helps. All I am doing to use ICE is I am adding Ice.jar into the class path, and I am using slice2java to generate the Java classes.
    mes wrote: »
    See the manual for details.

    Take care,
    - Mark

    On a first read, I am not sure this applies to my situation, but admittedly I am no Java expert.

    Regards,

    Karl
  • mes
    mes California
    As long as the class files for the generated code are in your CLASSPATH, the Ice run time should be able to unmarshal the objects. And I assume that the class files are in your CLASSPATH, otherwise your program wouldn't be able to run. Unless of course you are using Dynamic Ice to invoke GetCountries.

    It would also be helpful to see the full stack trace of the exception.

    - Mark
  • kwaclaw
    kwaclaw Oshawa, Canada
    mes wrote: »
    As long as the class files for the generated code are in your CLASSPATH, the Ice run time should be able to unmarshal the objects. And I assume that the class files are in your CLASSPATH, otherwise your program wouldn't be able to run. Unless of course you are using Dynamic Ice to invoke GetCountries.

    No, I am not using dynamic Ice, and the class path should be OK, otherwise the application would not run at all. The class path is to some degree configured on JBOSS, as the application is deployed into a JBOSS directory.
    mes wrote: »
    It would also be helpful to see the full stack trace of the exception.

    - Mark

    See below. Pretty long, but you asked for it. :-)

    Regards,

    Karl

    Stack trace:

    Ice.NoObjectFactoryException
    reason = ""
    type = "::IServices2ICE::Country"
    at IceInternal.BasicStream.readObject(BasicStream.java:1343)
    at IceInternal.BasicStream.readPendingObjects(BasicStream.java:1554)
    at IServices2ICE._CommonServicesDelM.GetCountries(_CommonServicesDelM.java:147)
    at IServices2ICE.CommonServicesPrxHelper.GetCountries(CommonServicesPrxHelper.java:184)
    at IServices2ICE.CommonServicesPrxHelper.GetCountries(CommonServicesPrxHelper.java:156)
    at iservices.WsCountryList.doGet(WsCountryList.java:40)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:697)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
    at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
    at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:39)
    at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:159)
    at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:59)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
    at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
    at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
    at java.lang.Thread.run(Unknown Source)
  • mes
    mes California
    Hi Karl,

    We don't have much experience with servlets, but I suspect the problem is caused by a Web server configuration issue or a security restriction that prevents the Ice run time in your servlet from loading a class dynamically, or a combination of the two. For example, perhaps the Web server only permits classes from a particular directory to be loaded dynamically.

    You should be able to verify with a simple standalone client that the unmarshaling works. If you still can't resolve the issue, I think your only recourse is to install object factories.

    Take care,
    - Mark
  • kwaclaw
    kwaclaw Oshawa, Canada
    mes wrote: »
    Hi Karl,

    We don't have much experience with servlets, but I suspect the problem is caused by a Web server configuration issue or a security restriction that prevents the Ice run time in your servlet from loading a class dynamically, or a combination of the two. For example, perhaps the Web server only permits classes from a particular directory to be loaded dynamically.

    You should be able to verify with a simple standalone client that the unmarshaling works. If you still can't resolve the issue, I think your only recourse is to install object factories.

    Take care,
    - Mark

    Yes, it works with a simple console application.
    I guess you are right, its probably a JBOSS security issue.

    Thanks for the help,

    Karl
  • kwaclaw
    kwaclaw Oshawa, Canada
    mes wrote: »
    Hi Karl,

    We don't have much experience with servlets, but I suspect the problem is
    caused by a Web server configuration issue or a security restriction that prevents the Ice run time in your servlet from loading a class dynamically, or a combination of the two. For example, perhaps the Web server only permits classes from a particular directory to be loaded dynamically.
    
    You should be able to verify with a simple standalone client that the unmarshaling works. If you still can't resolve the issue, I think your only recourse is to install object factories.
    
    Take care,
    - Mark[/QUOTE]
    
    Just one more observation to add: Not so sure that security is an issue, because dynamic class loading actually works. I simply installed a default object factory that basically does the same thing the ICE runtime does. Here is the main method:
    
    [code]
      public Object create(String type) {
        type = type.substring(2);
        String className = type.replaceAll("::", ".");
        try {
          Class c = Class.forName(className);
          return (Object)c.newInstance();
        }
        catch (Exception ex) {
          assert(false);
          return null;
        }
      }
    

    This seems to work without problems.

    Karl
  • kwaclaw wrote: »
    No, I have not added any metadata directives for Java to my Slice definitions.
    The application is a JBOSS application, if that helps. All I am doing to use ICE is I am adding Ice.jar into the class path, and I am using slice2java to generate the Java classes.
    In which directory of your JBOSS installation are you putting the jar ?
    kwaclaw wrote: »
    On a first read, I am not sure this applies to my situation, but admittedly I am no Java expert.

    Regards,

    Karl
    Well, taming the beast (JBOSS/J2EE) without being a Java expert could be a very exciting experience, really :eek:
    (It reminds me an editorial of a Connections Issue about learning C++ in 10 easy lessons - or something similar).


    Good luck ;)

    Guido
  • kwaclaw
    kwaclaw Oshawa, Canada
    ganzuoni wrote: »
    In which directory of your JBOSS installation are you putting the jar ?

    I am putting it into ..\jboss-4.0.3SP1\server\default\lib .
    Well, taming the beast (JBOSS/J2EE) without being a Java expert could be a very exciting experience, really :eek:
    (It reminds me an editorial of a Connections Issue about learning C++ in 10 easy lessons - or something similar).
    Guido

    Luckiliy I just had to do a proof of concept for using ICE with Java, and the experts are now taking over. :-)

    Karl
  • kwaclaw wrote: »
    I am putting it into ..\jboss-4.0.3SP1\server\default\lib .
    Remove from there and put in WEB-INF/lib of your webapp.
    Guido
  • kwaclaw
    kwaclaw Oshawa, Canada
    ganzuoni wrote: »
    Remove from there and put in WEB-INF/lib of your webapp.
    Guido

    Yes, that works!!! Many thanks!

    Not sure why, though, as my own object factory did work, just not the default one built into Ice.jar.

    Karl
  • kwaclaw wrote: »
    Yes, that works!!! Many thanks!

    Not sure why, though, as my own object factory did work, just not the default one built into Ice.jar.

    Karl
    Maybe ICE does not use the classloader attached to the current thread, so it cannot "see" classes that are loaded by the classloader of your webapp.
    You object factory instead is loaded by your webapp classloader.

    Guido
  • kwaclaw
    kwaclaw Oshawa, Canada
    ganzuoni wrote: »
    Maybe ICE does not use the classloader attached to the current thread, so it cannot "see" classes that are loaded by the classloader of your webapp.
    You object factory instead is loaded by your webapp classloader.

    Guido

    Yes, one of my avenues of research was to find out how JBOSS and ICE use class loaders, but obviously I didn't find the answer ...

    Thanks for your insights!

    Karl
  • kwaclaw wrote: »
    Yes, one of my avenues of research was to find out how JBOSS and ICE use class loaders, but obviously I didn't find the answer ...

    Thanks for your insights!

    Karl
    Beware of JBOSS classloader. I could run into troubles if you need to use
    different version of the same product in different web apps.
    Even if you put each jar in its onw app.
    I prefer Tomcat that has a clean and clever classloader architecture.

    Guido.
  • kwaclaw
    kwaclaw Oshawa, Canada
    ganzuoni wrote: »
    Beware of JBOSS classloader. I could run into troubles if you need to use
    different version of the same product in different web apps.
    Even if you put each jar in its onw app.
    I prefer Tomcat that has a clean and clever classloader architecture.

    Guido.

    I'll forward your note.
    Seems you have an axe to grind with JBOSS. ;)

    Karl