glassfish
  1. glassfish
  2. GLASSFISH-16078

RMI connections from appserver back to appclient for retrieving classes already present at the server.

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: entity-persistence
    • Labels:
      None
    • Environment:

      Glassfish 3.1 b41 on Windows XP

      Description

      We're deploying an Enterprise Application containing an embedded Application Client that's deployed to the client via Java Web Start.

      We have all the common artifacts inside the lib subdirectory of the .ear.

      The client calls an injected remote interface of a bean, which has a method like this:

      public void importConfiguration(TasksAndResources configuration);

      The class TaskAndResources is serializable, and contains JPA 2.0 entities inside, via Set<Task> and Set<Resource> member attributes. These are present both in the client dependencies and in the .ear lib subdirectory.

      However, when the client calls the above method, the Glassfish server connects back to the client (random RMI port listening) in order to retrieve the class definitions for Task, Resource, and ResourceRequirement (another entity that relates the former, but that's not directly referenced by the TaskAndResources class that's declared in the interface method).

      We've verified these call backs by using Wireshark and dumping the packets. The requests from the server to the client seem to use an operation called "meta".

      This seems rather strange. Why would the server need to download those classes, when they're already present in the .ear file, and a dependency (via MANIFEST.MF ClassPath attribute) to the called ejb implementation?

      Moreover, this breaks any hope we could have of being able to deploy the appclient when there's any kind of firewall between the client and the server. Since the callback port is random and non-configurable, we can't even create an ad-hoc rule.

      I guess there must be some classloader related problem when de-serializing the client request; the Task, Resource and ResourceRequirement classes aren't found in whatever classpath is used for that classloader (even if actually present in the .ear), and then they get requested from the client. The ejb call then succeeds, BTW.

      We detected this because the client would fail in client machines with more than one interface, when the random-port RMI server would declare a non-routable IP address for a local private interface.

        Activity

        Hide
        skandalfo added a comment - - edited

        BTW the only things injected to the application client are stateless session bean references.

        Show
        skandalfo added a comment - - edited BTW the only things injected to the application client are stateless session bean references.
        Hide
        skandalfo added a comment -

        I'll also include the layout of the .ear.

        The root files are a webapp, three EJB modules and the appclient module.

        Every EJB module has the @Local/@Remote interfaces that they implement in a correspondingly named -interfaces .jar file in the lib subdirectory.

        The shared persistence unit classes are in lib/kronos-model.jar, which also depends on lib/kronos-sink-interfaces.jar, lib/kronos-task-interfaces.jar and lib/kronos-trigger-interfaces.jar

        These are the files:

        META-INF
        META-INF\MANIFEST.MF
        lib
        kronos-client.jar
        kronos-ejb-trigger-cron.jar
        kronos-ejb-trigger-remote.jar
        kronos-ejb.jar
        kronos-webapp.war
        lib\antlr-runtime.jar
        lib\antlr.jar
        lib\client-log4j-configuration.jar
        lib\commons-codec.jar
        lib\commons-exec.jar
        lib\commons-io.jar
        lib\commons-jexl.jar
        lib\commons-lang.jar
        lib\commons-logging.jar
        lib\configuration-injector.jar
        lib\deferred-entity-listener.jar
        lib\kronos-cron-expressions.jar
        lib\kronos-ejb-interfaces.jar
        lib\kronos-ejb-trigger-cron-interfaces.jar
        lib\kronos-ejb-trigger-remote-interfaces.jar
        lib\kronos-listener-annotations.jar
        lib\kronos-logging-config.jar
        lib\kronos-model.jar
        lib\kronos-sink-email.jar
        lib\kronos-sink-interfaces.jar
        lib\kronos-task-commandline.jar
        lib\kronos-task-interfaces.jar
        lib\kronos-thread-pool.jar
        lib\kronos-trigger-cron.jar
        lib\kronos-trigger-interfaces.jar
        lib\kronos-trigger-remote.jar
        lib\log4j.jar
        lib\simple-xml.jar
        lib\stax-api.jar
        lib\stax.jar
        lib\stringtemplate.jar
        lib\text-processing.jar
        lib\winp.jar
        META-INF\application.xml
        META-INF\maven
        META-INF\maven\es.bbva.mgyd.kronos
        META-INF\maven\es.bbva.mgyd.kronos\kronos-application
        META-INF\maven\es.bbva.mgyd.kronos\kronos-application\pom.xml
        META-INF\maven\es.bbva.mgyd.kronos\kronos-application\pom.properties

        Show
        skandalfo added a comment - I'll also include the layout of the .ear. The root files are a webapp, three EJB modules and the appclient module. Every EJB module has the @Local/@Remote interfaces that they implement in a correspondingly named -interfaces .jar file in the lib subdirectory. The shared persistence unit classes are in lib/kronos-model.jar, which also depends on lib/kronos-sink-interfaces.jar, lib/kronos-task-interfaces.jar and lib/kronos-trigger-interfaces.jar These are the files: META-INF META-INF\MANIFEST.MF lib kronos-client.jar kronos-ejb-trigger-cron.jar kronos-ejb-trigger-remote.jar kronos-ejb.jar kronos-webapp.war lib\antlr-runtime.jar lib\antlr.jar lib\client-log4j-configuration.jar lib\commons-codec.jar lib\commons-exec.jar lib\commons-io.jar lib\commons-jexl.jar lib\commons-lang.jar lib\commons-logging.jar lib\configuration-injector.jar lib\deferred-entity-listener.jar lib\kronos-cron-expressions.jar lib\kronos-ejb-interfaces.jar lib\kronos-ejb-trigger-cron-interfaces.jar lib\kronos-ejb-trigger-remote-interfaces.jar lib\kronos-listener-annotations.jar lib\kronos-logging-config.jar lib\kronos-model.jar lib\kronos-sink-email.jar lib\kronos-sink-interfaces.jar lib\kronos-task-commandline.jar lib\kronos-task-interfaces.jar lib\kronos-thread-pool.jar lib\kronos-trigger-cron.jar lib\kronos-trigger-interfaces.jar lib\kronos-trigger-remote.jar lib\log4j.jar lib\simple-xml.jar lib\stax-api.jar lib\stax.jar lib\stringtemplate.jar lib\text-processing.jar lib\winp.jar META-INF\application.xml META-INF\maven META-INF\maven\es.bbva.mgyd.kronos META-INF\maven\es.bbva.mgyd.kronos\kronos-application META-INF\maven\es.bbva.mgyd.kronos\kronos-application\pom.xml META-INF\maven\es.bbva.mgyd.kronos\kronos-application\pom.properties
        Hide
        Mitesh Meswani added a comment -

        Thanks for all the information. You should be able to use static weaving to get benefits of weaving and not run into the issue. Can you please give it a try. You can find the instruction here http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_(ELUG)#How_to_Configure_Static_Weaving_for_JPA_Entities

        Show
        Mitesh Meswani added a comment - Thanks for all the information. You should be able to use static weaving to get benefits of weaving and not run into the issue. Can you please give it a try. You can find the instruction here http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_(ELUG)#How_to_Configure_Static_Weaving_for_JPA_Entities
        Hide
        skandalfo added a comment -

        We've tested, and it works correctly when using static weaving too.

        Show
        skandalfo added a comment - We've tested, and it works correctly when using static weaving too.
        Hide
        Mitesh Meswani added a comment -

        Thanks for confirming that static weaving works. The core issue here is that RMI-IIOP treats weaved and unweaved classes as different. Ken explains this very well in his blog (http://blogs.sun.com/ejcorba/entry/iiop_changes_in_glassfish_3). Relevant section is copied at [1]. Currently we would suggest you to use static weaving as a workaround to this issue. I am closing this issue as "won't fix"

        [1] From Ken's blog
        One very interesting issue that showed up in 3.1 is related to JPA. We have some applications in which the same class appears in both the client and the server, and is marshaled as part of an RMI-IIOP request. However, the class is one that is instrumented by the JPA bytecode weaver on the server side. New JPA behavior introduced in GlassFish 3.1 added a new field to the modified class, and this in turn changed the RMI-IIOP hashcode for the class. The result of this is that (as far as Java Serialization or RMI-IIOP marshaling semantics are concerned) the old class and the new class are now different versions of the same class, and special handling is needed. RMI-IIOP handles this case using a remote object called the full value descriptor (FVD), which is sent in an IIOP message the first time a value type is marshaled on a newly opened ORB connection. When the receiver of an object detects that the version of the object received is not the same as the version of the object in the receiving VM, a method named "meta" is invoked on the FVD. This introduces an extra round trip at the network level, considerably slowing the request processing. This problem affected issues 15816 and 16078. There is no easy ORB-level solution for this (caching meta data from FVDs may be possible, but would be a bit tricky). The solutions are either to change the behavior of the JPA weaver, or to make both sides (client and server) weave (or not) the same way.

        Show
        Mitesh Meswani added a comment - Thanks for confirming that static weaving works. The core issue here is that RMI-IIOP treats weaved and unweaved classes as different. Ken explains this very well in his blog ( http://blogs.sun.com/ejcorba/entry/iiop_changes_in_glassfish_3 ). Relevant section is copied at [1] . Currently we would suggest you to use static weaving as a workaround to this issue. I am closing this issue as "won't fix" [1] From Ken's blog One very interesting issue that showed up in 3.1 is related to JPA. We have some applications in which the same class appears in both the client and the server, and is marshaled as part of an RMI-IIOP request. However, the class is one that is instrumented by the JPA bytecode weaver on the server side. New JPA behavior introduced in GlassFish 3.1 added a new field to the modified class, and this in turn changed the RMI-IIOP hashcode for the class. The result of this is that (as far as Java Serialization or RMI-IIOP marshaling semantics are concerned) the old class and the new class are now different versions of the same class, and special handling is needed. RMI-IIOP handles this case using a remote object called the full value descriptor (FVD), which is sent in an IIOP message the first time a value type is marshaled on a newly opened ORB connection. When the receiver of an object detects that the version of the object received is not the same as the version of the object in the receiving VM, a method named "meta" is invoked on the FVD. This introduces an extra round trip at the network level, considerably slowing the request processing. This problem affected issues 15816 and 16078. There is no easy ORB-level solution for this (caching meta data from FVDs may be possible, but would be a bit tricky). The solutions are either to change the behavior of the JPA weaver, or to make both sides (client and server) weave (or not) the same way.

          People

          • Assignee:
            Mitesh Meswani
            Reporter:
            skandalfo
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: