This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.
Summary: | ear files with war and ejb are mispackaged | ||
---|---|---|---|
Product: | javaee | Reporter: | bbissett <bbissett> |
Component: | EAR | Assignee: | David Konecny <dkonecny> |
Status: | RESOLVED FIXED | ||
Severity: | blocker | CC: | alexismp, hongzhang, judytang, ludo, miteshm, pjiricka, tjquinn, vkraemer |
Priority: | P2 | ||
Version: | 6.x | ||
Hardware: | Macintosh | ||
OS: | All | ||
Issue Type: | DEFECT | Exception Reporter: | |
Attachments: |
the NB project
The built ear file |
Description
bbissett
2009-09-28 15:54:58 UTC
Created attachment 88436 [details]
the NB project
Created attachment 88437 [details]
The built ear file
bbissett, this problem should NOT happen if you do Clean and Build on EAR project. Could you confirm that please? If I do Clean and Build on EAR then WAR file inside EAR file does not contain EJB jar but just ClassPath reference in its manifest file which is correct. The problem you described happens when you first build just WAR project - that creates WAR file and includes entire EJB jar in it. And if you later build EAR then already built WAR file is included as is. That's something what should not happen and what causes "2 EJBs" problem. Referencing through the manifest is essentially the same thing as packaging the ejb jar in the war. The bean class just should not be visible to the war file. The follow comments are from the EJB spec lead Ken Saks: It was never legal in EE 5 to package a bean class containing a component-defining annotation in the .war (whether directly or via the manifest approach). The easiest repackaging approach is just to replicate the common interfaces and supporting types in the .war instead of using the .war manifest classpath. An alternative is to package the common interface code in a library .jar and put it in a directory named "lib" at the .ear level. In that case all code will be guaranteed visibility to both ejb-jars and .wars in the .ear. do we need the manifest entry at all if the war and ejb-jar are in the same ear? No, we don't and it should be removed. But the EJB interfaces that the web component depend on should be visible to the war (through packaging directly in the war or in the form of a library jar). to Hong: why? all the necessary classes needed by the war in the context of this EAR file are known and in the ejb jar... Introducing a new lib will complexify the build process, and as well the dir deploy structure, and compile on save (need to copy in 2 places the interface?) How does a maven ejb jar/ear project structure? What about EE 6 samples with ANT tasks? Pointers? The real reason this cp entry was introduced in Nb 5 for EE 5 was not a runtime error but a GF verifier tool error. Without the cp entry, I think the runtime was ok, so the war file in the context of the EAR file had access to the classes in the EJB jar packaged in that EAR file... I re-read chapters of specification on EAR packaging twice but either they are too vague or I missed relevant parts because some details are still unclear to me. Let's say I have couple of jars/projects: * entities.jar - Java class library project which packages JPA entity classes * ejbs.jar - EJB JAR project which is using using entities.jar and which is defining Session bean for entity class manipulation * web.jar - JSF Web Application project which is using entities.jar and ejbs.jar to access directly entity classes and also ejbs and present them in UI How these modules should be packaged into one EAR application? I found that GF2 and GF3 behave quite differently. I actually was not able to package EAR app to make it run properly on GF3 - entity classes cannot be resolved in runtime - regardless if I place entities.jar to EAR's lib folder or not and regardless if I use ClassPath manifest entry or not. I would appreciate if somebody could shed some light. Thanks. PS: I agree that generating separate JAR for EJB interfaces seems like overkill when both WAR and EJBJAR are in the same EAR. dkonecny, The simplest way to package the application is as follows app.ear web.jar ejb.jar META-INF/persitence.xml - persistence.xml contains following <jar-file>lib/earEntities.jar</jar-file> lib/ entity.jar (Notice no persistence.xml should be present here. See section 8.2 of JPA 2.0 spec for details) mitesh, thanks! <jarfile> made it clear to me. There is issue which I'm about to fix and which requests that all JAR files which are not J2EE modules are by default placed to EAR's lib folder (issue 163971). That makes these jars available to all J2EE modules in EAR and these JARs do not have to be listed in ClassPath manifest property. Re. "EJB interfaces that the web component depend on should be visible to the war (through packaging directly in the war or in the form of a library jar)" - this is still open question. dkonecny, I think I misread your post from "Wed Sep 30 00:19:40" last time. If you were trying following ear structure, it should work. app.ear web.jar ejb.jar lib/ entity.jar META-INF/persitence.xml Can you please try it against latest GlassFish nightly. Thanks, Mitesh Probably this part was never clearly stated in JavaEE5 Spec. This is what's in JavaEE6 Spec: EE.8.3.1Web Container Class Loading Requirements Components in the web container may have access to the following classes and resources. Portable applications must not depend on having or not having access to these classes or resources. •The classes and resources accessible to any other web modules included in the same ear file, as described above. •The content of any EJB jar files included in the same ear file. ... Mitesh, my problem was that I was not using <jar-file> tag properly (which somehow worked in GF2). Fixing that according to your advice made everything pretty straightforward. Regarding persistence.xml placement I followed specification chapter "8.2.2 Persistence Unit Scope" and that worked as expected so I more or less ignored your comment "entity.jar (Notice no persistence.xml should be present here. See section 8.2 of JPA 2.0 spec for details)". :-) Re. "EE.8.3.1Web Container Class Loading Requirements" - let me summarize solutions: At the moment code for EAR with EJB and WAR generated by NetBeans relies on ClassPath manifest attribute (WAR uses ClassPath manifest attribute to reference EJB). According to hongzhang "Referencing through the manifest is essentially the same thing as packaging the ejb jar in the war" which I tend to agree with and we should not be doing. Side note is that latest GF3 does not seem to follow that - it does not complain that "there are 2 ejbs in the application with [the same] interface" in case of ClassPath manifest attribute; but it does complain when EJB is packaged in WAR. Let's call this Solution1. Solution2 is slight modification of existing state: keep everything as is but do not generate ClassPath manifest attribute. That would mean that generated code would not be *portable* as defined in EE.8.3.1 - generated WAR would depend on having access to "The content of any EJB jar files included in the same ear file" which is optional requirement but which seems to be implemented by GF3 but which may not be implemented by other servers. How bad is it if NetBeans generate "non-portable" enterprise applications? Solution3 is "repackaging approach" - just replicate the common interfaces and supporting types in the war. An alternative is to package the common interface code in a library .jar and put it in a directory named "lib" at the .ear level". Am I clear and do I understand it right? Any other solutions? At this stage of NB68 development I would prefer to go with Solution1 or Solution2 despite neither of them being "perfect". Solution3 is a whole new feature. Comments/opinions highly appreciated. Thanks. Yes, I think you understand the situation fairly well and pretty clear about the three solutions :-) Correction for solution 1 though: the v3 does treat them the same. It complains about the manifest case also which is why this bug was filed. :-) I think it would be NetBeans (and plug in) teams' call whether to go with 2) or 3). Re. "the v3 does treat them the same. It complains about the manifest case also which is why this bug was filed" - no it does not. :-) I just re-tested it on glassfish-v3-b66 and in manifest case (Solution1) application is correctly deployed. The bug described in this issue is caused by EJB jar being wrongly included in WAR file which happens if you perform build of EAR project in certain steps - see my first comment in this issue for more details. But manifest case was never a problem. Thanks for confirming that my descriptions are clear - I wanted to make sure we are all on the same page. Re. "I think it would be NetBeans (and plug in) teams' call whether to go with 2) or 3)." - as Solution1 or Solution2 depends on implementation details of GF3 I would go with them only if GF team confirms they are going to support one of them. Did you try with the ear that was attached (SimpleWebEjb.ear)? Did it give you the failure when you tried to deploy it? Inside this ear, there is an ejb jar and war. In the war, there is no ejb jar packaged directly (nothing under WEB-INF/classes or WEB-INF/lib), but there is a Manifest file with Class-Path pointing to the ejb.jar. Am I missing something here? For solution 2, yes, this will work with glassfish v3. I would still recommend solution 3 as it's a portable approach but I understand there will be more work involved. Re. "Did you try with the ear that was attached (SimpleWebEjb.ear)?" - no, I never did. And trying it now I can see that deploying an EAR application in directory mode works fine but deploying it as EAR fails with "there are 2 ejbs in the application". Thanks, that drops Solution1. Re. "For solution 2, yes, this will work with glassfish v3." - great to hear! I will go ahead and make the changes on NetBeans side. I was looking through this issue, and realized that one update that I had meant to post was not in here.... Since my memory is a bit faded, you may want to take the following statement with a grain of salt... I did some experiments to try to reproduce this issue. I think I hit another way to generate the output that bbissett alludes to... Create an EAR project that includes an EJB jar project and a WAR project. create an ejb and a simple 'echo' business method create a servlet that calls that uses the ejb to call the echo method. Build the project from inside NB. go to the command-line and use asadmin deploy to deploy the EAR. Sorry to mention this so late in the process. I think my posting got jinxed by the network issues that netbeans.org had over the weekend of the Friday Oct 2 to Monday Oct 5... By fixing issue 163971 I resolved packaging problems identified here: no ClassPath manifest attribute is used; J2EE Modules are packaged in root of EAR and all other JARs are packaged in EAR's lib subfolder. What remains to be resolved in this issue is problem described in my first comment in this issue which is P3 issue. Can you clarify with some more details? Reading the other issues, I understand we now add a lib directory to the ear packaging and will not use manifest entry anymore. So for the attached application, what will be the resulting packaging now? What is inside the lib directory? Will the current packaged ear work with glassfish v3? (And what's "my first comment" referred to?) re. "for the attached application, what will be the resulting packaging now" - file layout will be the same - 2 J2EE Modules in root of EAR. The only difference is that SimpleWebEjb-war.war will not contain in its manifest following entry "Class-Path: SimpleWebEjb-ejb.jar". EAR's lib directory in this case is empty and therefore will not be created. An example when EAR's lib folder would be used is for example if your SimpleWebEjb-ejb.jar sample was depending on a SomeEntities.jar defining JPA entity classes - SomeEntities.jar would be packaged to EAR's lib folder so that both war and ejb can access these entity classes. war and ejb would not use ClassPath manifest entry to refer to SomeEntities.jar as everything in lib folder is available to all J2EE Modules. "my first comment" refers to my comment in this issue labelled "------- Additional comments from dkonecny Mon Sep 28 23:49:56 +0000 2009 -------". Ok, so the current packaged application will deploy on v3 with no problem. That's my main question :-) For you first comment, I thought we later found clean or not does not really make a difference? Anyways, that's not my main concern. hongzhang, yes deployment to GF3 as well as to GF2 works fine now. There is still one more problem in clean target of Web Project - that problem can result in whole ejb jar being packaged in war file which is then packaged in ear and which will result in "there are 2 ejbs in the application". But that error is triggered only by particular order of build steps and that's why I lowered importance of problem to P3. I plan to resolve that one as well. Now, one more question hongzhang about AppClient project packaging. If EJB and WAR and APPCLIENT are all packaged in EAR and APPCLIENT will access enterprise beans from EJB module then what should packaging of APPCLIENT look like. APPCLIENT.jar should be in EAR's root, right? and contrary to EJB and WAR it should contain ClassPath manifest entry listing EJB jar, right?? Just when I felt I know all the answers and everything should work fine I realized that APPCLIENT is most probably broken now (issue 174708). For appclient part, the correct (spec defined portable) packaging is to package the ejb interfaces that the appclient references inside the appclient jar (or put the interfaces in lib), just like what we should do for the war which references EJB. The reason it worked for war without manifest entry with glassfish is that in glassfish implementation the EJB classloader is the parent classloader of the Web classloader, so the classes in the war can automatically see all the EJB classes. But this is not the case with appclient, as the appclient loads in appclient container in client VM (issue 174708). Using the manifest in the appclient jar to include the ejb jar would work with glassfish for most cases, but it is really troublesome to do this. To give you an example, one problem that reported: one ejb references some connector class, when the appclient container loads the appclient in client VM, because the ejb jar was there, that ejb tries to look for the connector class which does not exist in client VM. I think you should probably spend some time to see if we can implement the packaging the proper way before using the manifest thing as the last resort. Hong's most recent entry is right on-target. Ideally the app client module will not depend on the EJB module. Some additional reasons... Doing so inflates the size of the downloadable bits needed for the app client. From the point of view of "clarity of app design" we do not want to encourage or institutionalize through NB exposing the EJB implementation classes to the client. The client should depend only on the interfaces and we should not encourage application structures which expose the EJB implementation classes to the client. I can see that placing the EJB interface(s) into a library JAR - accessible to all modules in the app including app clients - involves more engineering work in the tool but it's also the best practice we'd want to encourage. forgot to add myself to the cc list earlier Thanks tjquinn and hongzhang. I understand all the arguments in favour of a JAR file holding EJB interfaces and using such JAR from WAR/APPCLIENT. I don't think we can safely automate that process and generate EJB API JAR for user on the background. We could collect all Remote/Local/No-Interfaces and place them in a JAR but how to handle classes which are required by these API interfaces? I mean if a stateless session bean references in its Local interface a JPA entity class should we include that JPA entity class in EJB API JAR as well? or rather not? The other option is for users to make this separation of API themselves - create dedicated Java Class Project and place all EJB API there and use it from other J2EE Modules. Users can do it today though there is no extra support or encouragement to do that from IDE point of view. I understand that it is best practice but I do not like added overhead for developer so I'm not particularly keen on changing NetBeans EJB project to by default suggest to user to create two projects and place all EJB API into separate project. That sounds like overkill to me and something user's projects may have to grown into during the time. Any ideas how you imagine IDE should deal with this are welcome! I would like to raise this issue from P3 to P2 so it may be fixed faster, saw two FishCAT emails reporting hitting this issue, if we can fix this sooner, then it can save every one time. Thanks, Judy judytang: please add a pointer to the issue/reports that you think are similar to this issue. If you experience this problem on latest NB build then please file a new issue. I'm fixing the last remaining part of the problem: 3bc2aa4358cb Integrated into 'main-golden', will be available in build *200910221401* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress) Changeset: http://hg.netbeans.org/main-golden/rev/3bc2aa4358cb User: David Konecny <dkonecny@netbeans.org> Log: #173195 - make sure EJB jar is not packaged twice (in WAR and EAR) |