eclipse-ee4j / glassfish

Eclipse GlassFish
https://eclipse-ee4j.github.io/glassfish/
378 stars 144 forks source link

Client jar retrieved from EAR fails to find EJB #9068

Closed glassfishrobot closed 15 years ago

glassfishrobot commented 15 years ago

An application client jar that is part of an EAR that also contains an EJB jar fails to run. It can't find the EJB. This is another EE 5 app that ran fine on GF V2. The EAR file deploys just fine and the client jar file is retrieved, but an attempt to run the client blows up.

jdench 102 =>appclient -client client-jar/clientsessionmdbClient/clientsessionmdb-app-clientClient.jar Exception in thread "main" java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:323) at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:338) Caused by: java.lang.NoClassDefFoundError: Lsb/PublisherRemote; at java.lang.Class.getDeclaredFields0(Native Method) at java.lang.Class.privateGetDeclaredFields(Class.java:2291) at java.lang.Class.getDeclaredField(Class.java:1880) at com.sun.enterprise.deployment.util.DefaultDOLVisitor.acceptWithCL(DefaultDOLVisitor.java:350) at com.sun.enterprise.deployment.util.EjbBundleValidator.accept(EjbBundleValidator.java:185) at com.sun.enterprise.deployment.ApplicationClientDescriptor.visit(ApplicationClientDescriptor.java:657) at com.sun.enterprise.deployment.archivist.AppClientArchivist.validate(AppClientArchivist.java:149) at org.glassfish.appclient.client.acc.FacadeLaunchable.validateDescriptor(FacadeLaunchable.java:157) at org.glassfish.appclient.client.acc.AppClientContainer.completePreparation(AppClientContainer.java:341) at org.glassfish.appclient.client.acc.AppClientContainer.prepare(AppClientContainer.java:305) at org.glassfish.appclient.client.AppClientFacade.prepareACC(AppClientFacade.java:262) at org.glassfish.appclient.client.acc.agent.AppClientContainerAgent.premain(AppClientContainerAgent.java:75) ... 6 more Caused by: java.lang.ClassNotFoundException: sb.PublisherRemote at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) ... 18 more FATAL ERROR in native method: processing of -javaagent failed

I'll attach a zip file with the app so that you can see the sources as well as the jars.

Environment

Operating System: Solaris Platform: Sun

Affected Versions

[V3]

glassfishrobot commented 6 years ago
glassfishrobot commented 15 years ago

@glassfishrobot Commented chaase3 said: Created an attachment (id=3062) Zip file with ear, jars, sources

glassfishrobot commented 15 years ago

@glassfishrobot Commented @tjquinno said: Does the client declare its dependency on the EJB in its manifest Class-Path?

The Java EE 6 spec is much stricter about what JARs are to be made accessible to the submodules of an EAR. In v2 and earlier, all EJB JARs and all top-level JARs in the EAR were made accessible to the client. With the EE 6 spec stricter, so is the GlassFish v3 app client implementation.

Can you please try that - build the app client JAR so that its manifest Class-Path refers to the EJB JAR - and see if it works then?

glassfishrobot commented 15 years ago

@glassfishrobot Commented chaase3 said: Hmmm – so an EE 6 implementation is allowed to break EE 5 applications? Okay...

Checking the relevant spec info in javaee_platform-6_0-pr-spec.pdf, I find the following, none of which seems to be quite as strict as that:

EE.8.2.1 p. 158 – note "may"

A JAR format file (such as a .jar file, .war file, or .rar file) may reference a .jar file or directory by naming the referenced .jar file or directory in a Class-Path header in the referencing JAR file's Manifest file.

EE.8.4.1 p. 169 – stricter, but note "should" not "must"

Make sure that each component in the application properly describes any dependencies it may have on other components in the application. A Java EE application should not assume that all components in the application will be available on the class path of the application at run time. Each component might be loaded into a separate class loader with a separate namespace. If the classes in a JAR file depend on classes in another JAR file, the first JAR file should reference the second JAR file using the Class-Path mechanism.

EE.8.5.2 p. 175 – note references to annotations

3. If the module deployment descriptor is absent, or is present and is a Java EE 5 or later version descriptor and the metadata-complete attribute is not set to true, the deployment tool must examine all the class files in the application package that can be used by the module (that is, all class files that are included in the .ear file and can be referenced by the module, such as the class files included in the module itself, class files referenced from the module by use of a Class-Path reference, class files included in the library directory, etc.). Any annotations that specify deployment information must be logically merged with the information in the deployment descriptor (if present).

4. The deployment tool must install all of the components described by each module deployment descriptor, or marked via annotations and discovered as described in the previous requirement, into the appropriate container according to the deployment requirements of the respective Java EE component specification.

Anyway, I added the following to the manifest file for the client:

Class-Path: clientsessionmdb-ejb.jar

Now I get a different error:

jdench 179 =>appclient -client client-jar/clientsessionmdbClient.jar Aug 7, 2009 6:57:06 PM com.sun.enterprise.deployment.deploy.shared.InputJarArchive getJarFile WARNING: enterprise.deployment.backend.fileOpenFailure Aug 7, 2009 6:57:06 PM com.sun.enterprise.deployment.deploy.shared.InputJarArchive getJarFile WARNING: error in opening zip file – invalid zip file: jar:/home/chaase/ee6examples/examples/jms/clientsessionmdb/client-jar/ java.lang.NullPointerException at org.glassfish.appclient.client.acc.FacadeLaunchable.selectFacadeFromGroup(FacadeLaunchable.java:298) at org.glassfish.appclient.client.acc.FacadeLaunchable.newFacade(FacadeLaunchable.java:209) at org.glassfish.appclient.client.acc.Launchable$LaunchableUtil.newLaunchable(Launchable.java:99) at org.glassfish.appclient.client.acc.AppClientContainerBuilder.newContainer(AppClientContainerBuilder.java:142) at org.glassfish.appclient.client.AppClientFacade.createContainerForAppClientArchiveOrDir(AppClientFacade.java:447) at org.glassfish.appclient.client.AppClientFacade.createContainer(AppClientFacade.java:409) at org.glassfish.appclient.client.AppClientFacade.prepareACC(AppClientFacade.java:254) at org.glassfish.appclient.client.acc.agent.AppClientContainerAgent.premain(AppClientContainerAgent.java:75) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:323) at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:338)

All that is returned when I do "deploy --retrieve" is a client jar file, clientsessionmdbClient.jar, with a small Facade class in it. Without the Class-Path in the manifest file, I also got a much bigger client jar file, clientsessionmdb-app-clientClient.jar, with a bigger Facade class in it. Each results in a different runtime error. clientsessionmdb-app-clientClient.jar is in the zip I sent you; I'll attach the clientsessionmdbClient.jar.

glassfishrobot commented 15 years ago

@glassfishrobot Commented chaase3 said: Created an attachment (id=3065) client jar with small Facade class

glassfishrobot commented 15 years ago

@glassfishrobot Commented @tjquinno said: Oh, you omitted the fun part in EE 8.3.3 (Application Client Container Class Loading Requirements, p. 171) – note "must not":

Components in the application client container must not have access to the following classes and resources, unless such classes or resources are covered by one of the rules above. • Other classes or resources in the application package. For example, the application client should not have access to the classes in other application client jar files in the same ear file, nor should it have access to the classes in web applications or ejb jar files in the same ear file.

The "rules above" reference basically describes the usual Java SE techniques, the Java EE library directory in the EAR, and an unspecified implementation-specific way of deviating from the behavior mandated in the spec. In fact back in the spring we started discussing if and how to provide such a mechanism so v2 users could continue to work with their existing apps that depended on the v2 behavior that's now non-compliant; this issue has revived that conversation. (on the GlassFish arch mailing list)

Back to the issue at hand... Are there deployment errors in the server.log file by any chance? Usually when just the EAR-level facade JAR file appears with nothing in the lower-level directories there has been an error in the app client deployer as it worked on an app client module. (Yes, we know the error handling needs improvement.)

I'll also try your example as soon as I have a chance - thanks for taking the time to upload it.

glassfishrobot commented 15 years ago

@glassfishrobot Commented @tjquinno said: Sorry - the spec extract I quoted is on p. 168 of the public review draft of the spec. I was looking at a different draft, but the relevant content is the same.

glassfishrobot commented 15 years ago

@glassfishrobot Commented chaase3 said: Gosh! So an app client "must not have ... access to the classes in web applications or ejb jar files in the same ear file." Put that way, it appears that an application client must not be a client of an application??

On the other hand, the exceptions to this rule include the following: "Components in the application client container must have access to ... The Java EE API classes specified in Table EE.6-1 for the application client container." And Table EE.6-1 says that an App Client is supposed to have access to EJB 3.1 client APIs. Does that not include an EJB's remote interface? What is the remote interface for, if not to make it accessible to clients?

The EJB 3.1 PFD from 2/24/09 says, in Chapter 3, "Client View of a Session Bean", p. 42:

A remote client of an session bean can be another enterprise bean deployed in the same or different container; or it can be an arbitrary Java program, such as an application, applet, or servlet. The client view of a session bean can also be mapped to non-Java client environments, such as CORBA clients that are not written in the Java programming language. The interface used by a remote client of a session bean is implemented by the container as a remote business interface (or a remote EJBObject interface), and the remote client view of a session bean is location-independent. A client running in the same JVM as the session object uses the same API as a client running in a different JVM on the same or different machine.

Interestingly, it doesn't specifically mention an application client here. But the tutorial examples have been calling session bean methods from app clients since time immemorial.

I'll see what happens exactly in the server log and let you know.

glassfishrobot commented 15 years ago

@glassfishrobot Commented chaase3 said: When I deploy the app, these are the messages that appear in the server log. No errors, just some apparently innocuous warnings.

Aug 10, 2009 10:44:11 AM OSGiModuleImpl start INFO: Started bundle org.glassfish.deployment.admin [91] Aug 10, 2009 10:44:12 AM com.sun.ejb.containers.MessageBeanContainer cleanupResources WARNING: [MDBContainer] Current thread done cleanup()... Aug 10, 2009 10:44:12 AM INFO: Deployment expansion took 90 Aug 10, 2009 10:44:12 AM INFO: DOL Loading time151 Aug 10, 2009 10:44:13 AM com.sun.enterprise.connectors.jms.system.ActiveJmsResourceAdapter updateMDBRuntimeInfo INFO: endpoint.determine.destinationtype Aug 10, 2009 10:44:13 AM com.sun.logging.LogDomains$1 getResourceBundle WARNING: Can not find resource bundle for this logger. class name that failed: com.sun.enterprise.connectors.jms.system.ActiveJmsResourceAdapter Aug 10, 2009 10:44:13 AM com.sun.ejb.containers.BaseContainer initializeHome INFO: Portable JNDI names for EJB PublisherBean : [java:global/clientsessionmdb/clientsessionmdb-ejb/PublisherBean!sb.PublisherRemote, java:global/clientsessionmdb/clientsessionmdb-ejb/PublisherBean] Aug 10, 2009 10:44:13 AM com.sun.ejb.containers.BaseContainer initializeHome INFO: Glassfish-specific (Non-portable) JNDI names for EJB PublisherBean : [sb.PublisherRemote#sb.PublisherRemote, sb.PublisherRemote](#sb.PublisherRemote, sb.PublisherRemote) Aug 10, 2009 10:44:13 AM org.glassfish.deployment.admin.DeployCommand execute INFO: Deployment of clientsessionmdb done is 1,252 ms Aug 10, 2009 10:44:16 AM OSGiModuleImpl start INFO: Started bundle org.glassfish.appclient.server.appclient-server-core [180] Aug 10, 2009 10:44:16 AM org.glassfish.deployment.admin.DeployCommand retrieveArtifacts INFO: About to download artifact file:/home/chaase/glassfishv3/glassfish/domains/domain1/generated/xml/clientsessionmdb/clientsessionmdbClient.jar

glassfishrobot commented 15 years ago

@glassfishrobot Commented @tjquinno said: Briefly:

1. About "an application client must not be a client of an application??"

When read in their entirety these relevant sections simply require the client to be explicit about its dependencies on other JARs in the app (with the addition that JARs in the EAR's library directory must always be available). If the developer wants the client to have access to the EJB module, the EE 6 spec simply requires the app client's manifest to say so. I don't see the spec limiting what the developer may do in this regard; it limits what the app server implementation may do by default.

2. The technology APIs which EE-6.1 itemizes are the APIs described in the various specs. Therefore they include javax.ejb.Remote but not a particular app's interfaces which extend Remote or an app's classes which implement Remote. I don't think the spec views an app's classes and interfaces as part of the Java EE API which it specifies.

When I try to build the project you uploaded to try dpeloying it myself NB complains with this:

Cannot find ../../bp-project/main.xml imported from 9068/clientsessionmdb/build.xml

Is there another piece I need?

(I got errors trying to deploy the EAR in the dist directory).

glassfishrobot commented 15 years ago

@glassfishrobot Commented chaase3 said: Hey, I find that the application runs correctly with the following client manifest:

Manifest-Version: 1.0 Ant-Version: Apache Ant 1.7.1 Created-By: 10.0-b23 (Sun Microsystems Inc.) Main-Class: MyAppClient Class-Path: clientsessionmdb-ejb.jar

Previously I had put a space between the Main-Class and the Class-Path, like this:

Manifest-Version: 1.0

Ant-Version: Apache Ant 1.7.1

Created-By: 10.0-b23 (Sun Microsystems Inc.)

Main-Class: MyAppClient

Class-Path: clientsessionmdb-ejb.jar

With the space, the app fails with this error:

[echo] running application client container. [exec] Aug 10, 2009 1:12:57 PM com.sun.enterprise.deployment.deploy.shared.InputJarArchive getJarFile [exec] WARNING: enterprise.deployment.backend.fileOpenFailure [exec] Aug 10, 2009 1:12:57 PM com.sun.enterprise.deployment.deploy.shared.InputJarArchive getJarFile [exec] WARNING: error in opening zip file – invalid zip file: jar:/home/chaase/ee6examples/examples/jms/clientsessionmdb/client-jar/ [exec] java.lang.NullPointerException [exec] at org.glassfish.appclient.client.acc.FacadeLaunchable.selectFacadeFromGroup(FacadeLaunchable.java:298) ...

Should one vertical space make that much difference?

When it works, the following messages appear:

[exec] Aug 10, 2009 1:16:44 PM com.sun.enterprise.deployment.util.EjbBundleValidator accept [exec] WARNING: Unresolved : clientsessionmdb-ejb.jar#PublisherBean [exec] Aug 10, 2009 1:16:44 PM com.sun.enterprise.transaction.JavaEETransactionManagerSimplified initDelegates [exec] INFO: Using com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate as the delegate

Does the warning about the ejb-link mean anything?

In order to run the app you need some directories in the tutorial bundle. You might want to just go download the bundle – go to http://java.sun.com/javaee/5/docs/tutorial/doc/index.html and click the Download link. Then follow the instructions in "Building the Examples on the Command-Line Using Ant", http://java.sun.com/javaee/5/docs/tutorial/doc/bnaan.html, to create a bp-project/build.properties file and edit common/admin-password.txt.

This would enable you to check other EE 5 examples for EE 6 compatibility as needed.

glassfishrobot commented 15 years ago

@glassfishrobot Commented chaase3 said: Sorry, pasting in these text windows does funny things that aren't visible in the edit pane.

The only difference between the two manifest versions is a single vertical space between Main-Class and Class-Path.

glassfishrobot commented 15 years ago

@glassfishrobot Commented @tjquinno said: Any chance there was a trailing blank at the end of the Main-Class line?

Also, are you OK to close this issue at this point?

Thanks.

glassfishrobot commented 15 years ago

@glassfishrobot Commented chaase3 said: There's a trailing blank at the end of every line except the last line (and for the non-working one, the blank line), in both the working and the non-working versions of MANIFEST.MF.

If there's already a bug on the hypersensitive parsing of the manifest file (that is a bug, isn't it?), then you could close this one.

glassfishrobot commented 15 years ago

@glassfishrobot Commented @tjquinno said: Could you please either attach the working and non-working manifests or e-mail them as e-mail attachments to me?

All the code in the app client container and in deployment that deals with manifests uses the methods on Manifest in the Java libraries, so any hypersensitivity is there, not in GlassFish. Still, I'd like to understand what the problem is.

glassfishrobot commented 15 years ago

@glassfishrobot Commented chaase3 said: I'll attach both files. The spaces at the ends of the lines show up as ^M in vi – chances are someone worked on them in Windows and checked them in from there. It seems as if all of the manifest files in the tutorial examples are like that, and have been for a long time.

glassfishrobot commented 15 years ago

@glassfishrobot Commented chaase3 said: Created an attachment (id=3069) manifest file that works correctly

glassfishrobot commented 15 years ago

@glassfishrobot Commented chaase3 said: Created an attachment (id=3070) manifest file that results in runtime error

glassfishrobot commented 15 years ago

@glassfishrobot Commented @tjquinno said: The problem with the one manifest is that Java interprets the empty line as a separator between the main attributes in the manifest that apply to the JAR as a whole from per-entry attributes that give information about individual entries. The format for the per-entry attributes is:

Name: the-entry-name attr-1: value-1 attr-2: value-2

so the Manifest class did not accept the "bad" manifest because it tried to fit the Class-Path: entry into the per-entry format.

The app client container tries to get information from the client's manifest before launching the client, and we know it needs to be more defensive in some places, including this one.

I have opened issue 9092 (https://glassfish.dev.java.net/issues/show_bug.cgi?id=9092) to record that problem. I think it's clearer that way rather than changing this issue to reflect that problem. It'll be helpful to have this issue and its current title in case others run into similar problems in the future.

I'm also closing this issue in light of the chaase3's success with the revised manifest. I'm using "invalid" - a status I really do not like - to indicate that the behavior in GlassFish is as desired. That status does NOT mean I don't think this was a legitimate concern but rather it's the closest we have to "not a defect."

glassfishrobot commented 15 years ago

@glassfishrobot Commented File: clientsessionmdb.zip Attached By: chaase3

glassfishrobot commented 15 years ago

@glassfishrobot Commented File: clientsessionmdbClient.jar Attached By: chaase3

glassfishrobot commented 15 years ago

@glassfishrobot Commented File: MANIFEST.MF Attached By: chaase3

glassfishrobot commented 15 years ago

@glassfishrobot Commented File: MANIFEST.MF Attached By: chaase3

glassfishrobot commented 7 years ago

@glassfishrobot Commented This issue was imported from java.net JIRA GLASSFISH-9068

glassfishrobot commented 15 years ago

@glassfishrobot Commented Reported by chaase3

glassfishrobot commented 15 years ago

@glassfishrobot Commented Marked as incomplete on Monday, August 10th 2009, 10:56:40 pm