Glassfish 3 EJB Injection from the jar archive fails - java

I have a strange problem with EJB injection in the glassfish 3. Maybe I just not completely understand what I do :)
So this is a problem: My project consists of 2 modules that will be assembled with gradle.
Module A
Module B
Module A is a usual glassfish module that also works fine. Module B contains general purpose staff. Module B is also a dependency of A. Module A will be deployed to glassfish as a *.war archive and Module B is in the appropriate lib folder as *.jar archive:
module-a.war and somewere inside of it ../lib/module-b.jar
What I want is: Create in the Module B a "general purpose" stateless bean and use it in the Module A. But it doesn't work...
In the Module B I created a bean:
#Stateless
public class GeneralPurposeBean {}
and I try to use it in the Module A as follows:
...
#EJB
private GeneralPurposeBean genPurpBean;
...
So how I already mentioned the GeneralPurposeBean is in the *.jar
Each time when I try to use the bean it fails with following exception:
javax.ejb.CreateException: Could not create stateless EJB
When I move the bean to the Module A it works fine but I want share this bean with other modules, that will be developed in the future. Can someone explain to me what is wrong here? So the bean will be recognized but it can't be created. What I found out through debugging is that
JCDIServiceImpl#_createJCDIInjectionContext
Doesn't recognize the bean as an enterprise bean. So everything in the *.war that directly accessible will be properly created but not what lies in the *.jar's.

For the case someone has the same problem:
If you treat one of your modules as a dependency and this module contains EJB beans you want be injected the solution for my problem was to put /META-INF/beans.xml file into the module. Otherwise container doesn't recognize the beans as EJB.
That's it.

Related

Valid project structure in EAR

I have an application packed in .ear file. This is the structure:
EmployeeManager
|---EmployeeManagerEJB.jar
---src/ (1)
|---EmployeeManagerJSF.war/
---index.xhtml
---WEB-INF/
---classes/ (2)
---lib/
|---lib/
---EmployeeManagerIntegration.jar
---src/ (3)
I use CDI to inject to classes located in (2) EJBs which interfaces are in (3) and implementations are in (1). However CDI throws exception " Unsatisfied dependencies for type ...". I assume something is wrong with my EAR structure. What should I do to fix this thing up?
CDI does not work by default between sub-deployments as they do not use the same classloader.
You could try placing your CDI beans in the EAR/lib folder this may work
make sure all sub-deployments have beans.xml in them if they are using CDI
there is no reason for this to be an EAR deployment, you can put both jars in WAR/lib and things will work fine
You can define inter-sub-deployment dependencies by adding class-path values into meta-inf/manifest.mf (This is somewhat standard between containers, here's the wildfly example: https://docs.jboss.org/author/display/WFLY8/Class+Loading+in+WildFly)
Or you can rely on your container implementation and turn off sub-deployment isolation (For wildfly see the following: https://docs.jboss.org/author/display/WFLY8/Class+Loading+in+WildFly)
You could copy your CDI beans to each sub-deployment that use them

Cannot put EJB in a separate jar

I have an EJB with some JPA logic that I use in my java EE projects.
Instead of copying the class in every project I'm trying to put it in a separate jar, so I have this structure:
Java EE project with EJB and WAR projects in it
JPALogic: JAR project with JPALogic class in it
RemoteServices: JAR project with beans interfaces
Services: EJB project with beans, including JPALogic and RemoteServices as libraries
Frontend: WAR project with frontend, including RemoteServices as library.
JPALogic is used only in the EJB project and there's no reference to it in other parts of the Java EE app. In JPALogic library I've my JPALogic bean:
#Stateless
#LocalBean
public class JPALogic {
#Resource
private EJBContext ejbContext;
#Inject #ShardedPersistenceContext
private EntityManager em;
public JPALogic() {
}
[...lots of methods...]
}
It works perfect if JPALogic code is directly in the EJB project, but when I put it in the external library deployment become very unstable (netbeans 8 + glassfish 4) and almost every deploy fail with this error:
Exception while deploying the app [app] : Cannot resolve reference [Remote ejb-ref name=com.my.autenticacion.services.AutRolBackendServices/jpa,Remote 3.x interface =com.my.infraestructura.jpa.JPALogic,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session] because there are [2] ejbs in the application with interface com.my.infraestructura.jpa.JPALogic.
I've search but it seems this kind of error appear when an interface have more than one implementation, and this is not the case: there's only one bean named "JPALogic" and, inspecting the ear, JPALogic.jar appear one time only.
I'm doing something wrong?
If you jar contains EJB annotations (#Singleton, #Stateless, #Stateful component-defining annotations), its not a simple jar, but an ejb-jar, and should be packaged as a module.
Solution:
You should reference the JPALogic.jar in application.xml as an EJB module.
You can also add a "Class-Path: JPALogic.jar" in the META-INF/MANIFEST.MF of the referencing modules to garantee visibility. It could be visibile, depending on the container.
Like this:
application.EAR
META-INF/application.xml
(must have a reference to the JPALogic.jar EJB module)
JPALogic.jar (EJB-JAR)
remoteservices.jar
services.jar
META-INF/MANITESF.MF Class-Path: JPALogic.jar
remoteservices.jar
frontend.war
For a more details, refer to the JAVA EE 6 specification, chapter EE.8:
EE.8.3.2 EJB Container Class Loading Requirements
EE.8.5.2 Deploying a Java EE Application

NoClassDefFoundException in N-tier application

I am building a project for a class that I am taking, and it consists of 4 modules
-impl (business logic/dao access)
-ejb (encapsulates business logic and provides access to it via a remote interface)
-war (web tier)
-ear (contains the war and ejb modules)
One utility class that I have inside the impl is able to populate an H2 database. It does this by running an ingestor that reads in an processes an xml file that resides in a maven repository, using various dao classes/methods to ingest the data:
String fileName = "xml/proj-data.xml";
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
When I run the ingestor through a unit test, it runs fine, but when I have everything layered, I get the NoClassDefFoundException on xml/proj-data.xml
So the basic outline that I have is:
-the war has dependencies on the impl and ejb modules
-the ejb has dependency on the impl module
-the ear has dependency on the impl, ejb, and war
This is a maven project. When I deploy the EAR to the server, the start page for the war is displayed (as I expect).
-The html page has a button that when pressed, does a post to a servlet
-The servlet has an ejb injected into it that it calls (via its remote interface).
-The ejb method makes a call back to the populate method in the impl, and thats when the exception happens, and I get a webpage back showing the exception.
Do I need to declare that repository in the WAR pom file as well?
In typing the question, I think I know what the problem may be. The repository that the xml file resides in is declared in the root pom for the project(the impl parent), NOT the pom for the impl module. Since the impl is the module that gets packaged with the EAR, I may need to declare the repository in the impl pom file as well.

Annotation-specified bean name conflicts with existing, non-compatible bean definition

I'm using Spring 2.5.4 and am creating a Java application that I'm deploying onto Weblogic.
I have a class in an external library (which included in the WEB-INF/classes directory of the resulting WAR file of my application) that I want to use in my code. I've created an instance variable for an object of the class in my code and added the #Autowired annotation and a getter and setter. In my application context file I have declared a bean of the library class' type and added the following:
<context:annotation-config />
<context:component-scan base-package="com.mycompany" />
... in order to register an AutowiredAnnotationBeanPostProcessor that will scan the classes and process the annotation.
When I try and deploy the application, I get the following error:
java.lang.IllegalStateException: Annotation-specified bean name 'myBean' for bean
class [com.mycompany.package.ClassName] conflicts with existing, non-compatible
bean definition of same name and class [com.mycompany.otherPackage.ClassName]
I think this is because there's a class in the library which has the same name as one in my application code (both class' package names start with "com.mycompany"). Nb. this is NOT the class that I have added, but a different one. Is there any way I can circumvent this problem without changing the name of the class in my application?
Thanks for any assistance.
Old question but throwing my 2c of bad experience with similar problem.
If you have 2 classes with same name, but in different packages was there a time when you had your other class referenced by the failing Spring context? If so, I'd recommend to clean the AS cached files (typically the place where the WAR is extracted), clean/rebuild your WAR and deploy again. Restarting the app server is also recommended.
I found that application servers and web containers alike (Weblogic, WAS, Jboss, Tomcat) tend to leave behind the old classes and when application is deployed those stale .class files are loaded in JVM via some old references, which most of the time messes up the Spring context loader.
Typical scenario is when you have renamed/moved a class from one package to another, or even kept the package name the same but moved it to another module (jar). In such cases cached (left over) files in the AS work directory can cause big headaches. Wiping out the work directory in your AS should resolve the issue outright.
You should use #qualifier to avoid this kind of conflict please refer section 3.9.3.
I fixed the problem by removing the autowiring completely and accessing the bean by explicitly creating a reference to it through the application context and the getBean() method.
This would better fit as a comment to #Pavel Lechev's answer, but I don't have enough rep to comment yet.
For other's finding this, here's what I did to solve this problem. I am using Wildfly 9.0.2.Final and, IntelliJ IDEA 2016.1.3 Build #IU-145.1617. These steps should presumably work with JBoss as well.
Stop Wildfly server.
Navigate to $WILDFLY_HOME/standalone/. Delete the three following folders: lib/, log/ and temp/.
In IntelliJ, Build > Build Artifacts > All Artifacts > Clean (or just the artifacts you are deploying).
In IntelliJ, Build > Rebuild Project
Restart Wildfly and redeploy your artifact(s).
These steps remedied my issue of duplicate bean names detected in the Spring context after refactoring a package name upstream from a couple of Controllers.

Classloader problem with EJB

I'm working on a project which includes persistence library (JPA 1.2), EJB 3 and Web presentation layer (JSF). I develop application using Eclipse and application is published on Websphere Application Server Community Edition (Geronimo 2.1.4) through eclipse plugin (but the same thing happens if I publish manually). When publishing to server I get the following error:
java.lang.NoClassDefFoundError: Could not fully load class: manager.administration.vehicles.VehicleTypeAdminBean
due to:manager/vehicles/VehicleType
in classLoader:
org.apache.geronimo.kernel.classloader.TemporaryClassLoader#18878c7
at org.apache.xbean.finder.ClassFinder.(ClassFinder.java:177)
at org.apache.xbean.finder.ClassFinder.(ClassFinder.java:146)...
In web.xml I have reference to EJB:
<ejb-local-ref>
<ejb-ref-name>ejb/VehicleTypeAdmin</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>manager.administration.vehicles.VehicleTypeAdmin</local>
<ejb-link>VehicleTypeAdminBean</ejb-link>
</ejb-local-ref>
EJB project has a reference to persistence project, and Web project has references to both projects. I don't get any compilation errors, so I suppose classes and references are correct.
I don't know if it is app server problem, but I ran previously application on the same server using same configuration parameters.
Does anybody have a clue what might be the problem?
Looks almost like it couldn't find the class manager.vehicles.VehicleType when it was attempting to create/load the class manager.administration.vehicles.VehicleTypeAdminBean.
I've encountered similar problems before. When the class loader attempts to load the class it looks at the import statements (and other class usage declarations) and then attempts to load those classes and so on until it reaches the bottom of the chain (ie java.lang.Object). If it cannot find one class along the chain (in your case it looks like it cannot load VehicleType) then it will state that it cannot load the class at the top of the chain (in your case VehicleTypeAdminBean).
Is the VehicleType class in a different jar? If you have a web module and and EJB module do you have the jar containing the VehicleType class in the appropriate place(s). Sometimes with web projects you have to put the jars in the WebContent/WEB-INF/lib folder or it won't find them.
Are both of these projects deployed separately (ie. two ears? or one ear and one war?) or are they together (ie, one ear with jars and a war inside?). I'm assuming the second given you declared your EJB local?
The jars that you are dependent on also have to be declared in your MANIFEST.MF files in the projects that use it.
I'm kind of running on guesses since I do not know your project structure. Showing that would help quite a bit. But I'd still check on where VehicleType is located with regards to your EJB class. You might find it isn't where you think it is come packaging or runtime.
Thanks #Chris for WebContent/WEB-INF/lib idea ! it works for me by following these steps :
1- Export my EJBs to a JAR (MyEJBs.jar)
2- I created another jar with your_installation_path/IBM/SDP/runtimes/your_version/binCreateEJBStrub.bat via CMD.exe, by executing this command :
createEJBStubs.bat <my_path>/MyEJBs.jar -newfile –quiet
3- A new jar will be automatically created in the same directory as MyEJBs.jar named MyEJBs_withStubs.jar
4- Put your new jar in WebContent/WEB-INF/lib
5- Call your EJBs by :
MyEJBRemote eJBRemote;
InitialContext ic = new InitialContext();
obj = ic.lookup("your_ejb_name_jndi");
eJBRemote = (MyEJBRemote ) PortableRemoteObject.narrow(obj,
MyEJBRemote.class);
eJBRemote = (MyEJBRemote ) obj;
Now you can call your EJBs from another EAR

Categories

Resources