NoClassDefFoundError when trying to load class - java

I am getting a java.lang.NoClassDefFoundError when trying to instantiate some class
I will try to simplify the structure of my projects: I have 2 jar files A (with a.class inside) and B (with b.class) I am trying to instantiate a 'b' class inside 'a' code. JAR A is dependant on JAR B. JAR A is a regular JAR file which is located in application/lib and JAR B is packaged as an EJB_JAR.
I am using glassfish and J2EE with maven I am new to J2EE and I have tried to look up a little for it. I have figured out it might be a class loaders issue, as the Classloader that loads classes from lib ( A) is the Ancestor of the Classloader that loads EARs WARs and EJB_JARs hence because of visibility issues I cannot load class 'b' from 'a'
Also, when I'm trying invoke (using the "expression evaluator") Class.forName("com.package.SomeClass") in the debugger from classes located in Jar-A to load class in JAR-A I get a class, but when I try to load classes located in Jar-B I get the java.lang.NoClassDefFoundError exception.
The thing is, that the passed EJB in the constructor has all the EJB fields properly, so I thought it should work, and, everything was compiled successfully.
How do I solve this problem?
The weirdest thing:
I am using drools which resides in JAR_A and JAR_A has some regular class which tries to call b.class (in JAR_B)
calling b.class from a.class doesnt work,
but calling b.class directly from a rule (which got b.class from CommandFactory.newSetGlobal("Bclass",b))works just fine.
How Could it be?
when I pass it as an Object from JAR_B it works and invokates fine.

Recap
You say:
I am trying to instantiate a 'b' class inside 'a' code. JAR A is dependant on JAR B. JAR A is a regular JAR file which is located in application/lib and JAR B is packaged as an EJB_JAR.
From what I understand, you have a pom.xml to build jar A, which states that jar B is its <dependency/>.
Then I see two possible cases for your deployment scenarios: you are either deploying the jars to the application server as an EAR, where jar A is contained inside this EAR as a library and jar B is a deployment inside it, or you are trying to use B from another, unrelated application.
In either deployment case, this is an error, but it might be due to expressing your dependencies incorrectly, or accessing the EJB incorrectly.
Nested Deployment case
If this is a nested deployment, where jar A is contained in the EAR as a library, you have a dependency expression problem. An EAR library can not have a dependency on the EAR itself, it can only be the other way around. After all, this is the definition of a library, right? :)
You have to refactor your application to match the use case you are trying to implement here. For more info, see the excellent Patterns of Modular Architecture RefCard from DZone.
Application client case
If what you are writing is an isolated (might even be a standalone) client that is going to invoke some operations on the EJB, what you should do is create an interface (local or remote, depending on how you are deploying the client) and package it with the client application and your EJB.
Then use a JNDI lookup in your client application to obtain a reference to the remote EJB and use it via the interface:
Context foo = new InitialContext(remoteJndiServiceProperties);
MyBeanInterface bar = (MyBeanInterface)foo.lookup("com.mycompany.MyBeanInterface");
bar.doStuff();
The remote JNDI registry properties and your bean's business interface name have to be expressed properly, of course. See the EJB FAQ for Glassfish for more info.
It is even simpler if your client is running in the same deployment unit - you can just use the #EJB annotation in that case and inject a no-interface EJB reference.
For more information on standalone clients with GlassFish, see the Developing Application Clients with ACC guide which covers all possible deployment scenarios.
Some theory behind this
Run the application in a debugger (or look at the heap dump taken while your client is invoking methods on the EJB, passing it objects as parameters).
What you will see is that the EJB container (that is, your EJB) is not working with the actual class you think it is, but rather with something called a static proxy class, which is generated on the fly by the container.
Because of this, when you invoke the instanceof operator inside the EJB, checking if the class you're working with is of the correct type, it will evaluate to true, but when you try to typecast it, you will get a ClassCastException.
This is required by the EJB specification and there is not much you can do about it, except pass the objects not as references, but rather as serialized data (which is going to cost you).
It works the other way around, too, because the container must be able to intercept anything done to the EJB from outside of it, and react (such as unauthorized use of restricted methods, transaction handling, etc.).
BTW, a lot of what you are describing above is illegal. ;)
Manually loading classes using Class.forName() inside an EJB container, for example - the EJB container should manage the lifecycle of your objects and anything you can not obtain using a factory method, or even better, using "compatible" mechanisms such as CDI producers and dependency injection, should be passed to your EJBs as a parameter.
What is also questionable is the way you try to pass an instance of the EJB to an application running outside of the container. If you need to access your EJBs to invoke methods on them, you should do it by means of an EJB client, in your case most probably through a remote interface.
Also, look up the definition of classloader hell if you still want to pursue your approach - you might want to start with this article, but I guess it's just as good as any other.

Related

Run main method in EJB on Deployment of EAR

I have created one java project which has one Main class. So I am running this Java Project using this Main class main method . But now my requirement is changed that I have to create the EJB of this project, and deployable artifact will be EAR. So still in the search of that how i will run this main method on the deployment of this EAR in Websphere.
Just want to summarize that I want to execute main method in EJB on the deployment of EAR in WebSphere, searched a lot try one or two methods but still searching for some good way.
From your question and comments it is not entirely clear to me if you fully understand how EJBs work (i.e. their lifecycle, how they get called, etc.). If you haven't done so, I recommend reading a Java EE tutorial, e.g. this one from Oracle.
Once you have an overview how things work, have a look here and choose the way which fits best for your case.
Common to all ways is that you cannot have a main method as before, but you have to convert it to a normal public method of your EJB which will get called at startup.
Since you are using and EAR anyway, you can also package a WAR inside the EAR along your EJB, and then use the ContextListener method described in my link.
But also nowadays there is almost no need to have an EAR. You could package everything in a WAR. See here: Why use an ear instead of a war?
As far as I know, if you're on Java EE 6 and you want your EJBs methods to be called in a scheduled manner, you can make a scheduler EJB by annotating it with #Schedule, inject your EJBs in it and make the scheduled method to call your injected EJBs methods. If that's not the case and you want to call them on demand, you need a client like a Servlet in which you inject them.

How to inject a CDI managed bean that exists in another classloader

I am working on a framework which will be used in Java EE applications and therefore is likely to be deployed in the \lib directory of an EAR file.
The framework will use CDI to programmatically lookup and inject beans that are located in the Java EE application that is using the framework. The problem I've got is when the Provider.get() method from javax.enterprise.Provider<T> is called by my framework to get an instance of the bean, Weld throws a UnsatisfiedResolutionException.
To check this isn't an issue related to CDI I've also tried using MyClass myClass = Class.forName(clazz).newInstance(); to get an instance of the class but a ClassNotFoundException is thrown.
The structure of EAR file I'm using for testing purposes is as follows:
MyTestApp.ear
+\lib\MyFramework.jar <----Contains the framework invoking the Provider.get() method
+MyTestApp.jar <----Contains the bean I want to inject
My test application's EAR contains an application.xml file which includes <library-directory>lib</library-directory>.
I believe this problem is occurring because the bean I want to inject exists in a separate classloader. i.e. \lib\MyFramework.jar is in a different classloader to MyTestApp.jar. I found this SO question which seems to suggest this is the case. Given that I'm developing a framework I don't believe the answer in the question is a viable solution for my needs.
I'm intrigued to find out whether creating a CDI portable extension would allow me to get an instance of the bean I want to use, but don't have enough experience in this area. Using #Observes ProcessAnnotatedType<T> I can see beans that exist outside of the \lib directory in an EAR file, including the ones I want to programmatically inject.
My questions are:
Am I correct in assuming this problem is occurring because \lib\MyFramework.jar and MyTestApp.jar are in separate classloaders?
Is there anything I can do using CDI that will allow my framework when deployed in the \lib directory of an EAR file to make the Provider.get() method call to avoid Weld throwing a UnsatisfiedResolutionException?
Is there anything I can do outside of CDI to achieve same result?
Update
I've now tried moving MyFramework.jar to the root of the EAR file and also including the jar module in the application.xml file but the container fails to start the application due to a CDI unsatisfied dependency exception. The bean referenced in the exception can be injected when MyFramework.jar is located in the \lib directory and is a different bean to the one referenced in my question.
1 : yes
2 : actually I don't know
3 : Yes, you must understand the ear classloader hierarchy, the jars in ear lib directory are loaded at the ear level and so available in all child classloaders (there is one child classloader per component in the ear).
It means that MyFramework.jar is visible from MyTestApp.jar ear child classloader but the inverse is false.
see In java EE, which jars should I put in the library dir?
You can either :
move MyTestApp.jar to ear lib directory (MyFramework.jar can be either in lib dir and reference MyTestApp.jar or at ear root)
move MyFramework.jar at ear root and reference MyTestApp.jar in its manifest classpath
see Deployment of multiple, depended CDI jars in one EAR
It seems to me that it might be a poor architectural decision to have your "framework" depend on your application implementation. Perhaps it should be that your application that implements some framework-level interface to achieve your goal. As you have it, or would like it to work, suggests that an application, any application really, in your ear could influence the operation of all other applications in your ear by providing implementation to the framework. This seems like a bad idea to me. And if you were able to make this work and more that one application in your ear provided this implementation, CDI may still fail because of ambiguous dependencies.
There may be some container specific dependency configurations that you might be able employ. WildFly, for example, allows you to configure module-to-module dependencies. I think, it might be possible, in WildFly, for an ear to depend on a war.
While the above might work, after thinking about it, I this it is also a bad idea. You should really take a hard look at what you are really trying to do. I think if you take a harder look at what you are trying to do, you will discover that your will probably be able to peal out or abstract some dependencies and still provide implementation to the framework, but not from the applications in the ear.

How does a web server/container treat a POJO in respect to other classes like EJB's and Entities?

I'm trying to use plain old java objects(POJO)'s and regular class files where needed and only use EJBs when I need the functionality that they add such as asynchronous calls, pooling, etc. I'm wondering how the server treats this behavior once the project is deployed on a server. Since it is not managed by the container does a new instance have to be created for every stateless session bean pooled that might call one of it's methods? How do things like static methods or state affect this model.
Edit:
1) I can clarify more. The point of Java EE is that you annotate a POJO with #stateless etc so that a container can manage it. You don't have to declare a new instance of a stateless bean you just inject and can make calls to it's type.
2) Most Java EE tutorials and books never mention non annotated classes as a part of your business logic. It's never brought up. This seems strange to me if you can use them in Java EE projects for your business logic and it can get deployed on a server. If you don't need pooling or asynchronous access--the things that a container helps manager through an EJB then you can use theses regular POJO's in your Java EE project.
3) that leads me to my question which is how do I incorporate properly into a project? Do I put them in the EJB project that's connected to an EAR or should they go in the EAR? or Dynamic web project. There is almost no mention or instruction on proper use of regular objects like this. When it gets compiled into a WAR for deployment are there any issues you run into on the server? Isn't it expecting properly annotated EJBs, servlets or JSP?
The don't affect it at all. Classes are classes, objects are objects. They're no managed, they're not interfered with, nothing happens to them. They're not special is any way.
Static singletons are static singletons, Java is java.
All you need to be aware of is the classloader layout of your container, and how it relates to your deployed applications and resources. (Classes in one app can't see classes in another app, for example.) Most of the time it's not really important. Sometimes, it is, as things get more complicated.
But for the most part, it's just Java.
Addenda:
A better way to look at this is to simply group your classes up in to blocks of locality.
Let's take a simple web app that uses EJBs.
The web app is deployed in a WAR artifact, and the EJBs can be deployed separately, as individual EJBs in the container, or, more likely, in an EAR. When you package your application in an EAR, you will likely bundle the WAR within the EAR as well. So, in the end the EAR contains your WAR, and your EJBs.
Now during development, in this case, you're going to have classes that have are in one of three categories.
Classes that are relevant solely to the EJBs (for example the Session Beans).
Classes that are relevant solely to the WARs (such as a Servlet class).
Classes that are relevant to both (a database entity perhaps).
So, a simple way to package them is in three jar files. A jar file for your WAR (in fact, this is the WAR, with the classes in WEB-INF/classes), a jar file for your EJBs, and a jar file for the 3rd type, we'll call that a library.
In terms of build dependency, the WAR build depends on the lib, and the EJB build depends on the lib. But neither the WAR nor EJB depend on each other, as they don't share anything directly, only indirectly through the 3rd library jar. The lib jar is stand alone, since it doesn't have any dependency on either the WAR or EJBs. Note, your EJB Session Bean interface classes will go in to the library jar (since both tiers rely upon them).
In your ear, you simply bundle the lib jar, the WAR, and the EJB jar along with a META-INF dir and an application.xml file. The WAR has its own structure, with the WEB-INF and all, the EJB jar has its META-INF and ejb-jar.xml. But of note is the that lib.jar is NOT in the WEB-INF/lib directory, it's in the EAR bundle and thus shared by both the EJBs and the WAR using class loader chicanery that the container is responsible for.
This is important to note. For example, if you have, say, a simple static Singleton in your lib jar, then BOTH the WAR and EJBs will share that Singleton, since they're all part of the same class loader. To use that Singleton, it's just normal Java. Nothing special there.
If the EJB and WAR were deployed separately, they would EACH need there own copy of the lib.jar, and in the case of the Singleton, they would NOT share it, since each module would have it's own class loader.
So, barring some real burning need otherwise, it's easier to bundle everything in to an EAR and treat both the EJB tier and WAR tier as a single, integrated application.
Addenda 2:
People don't much talk about using classes in Java EE development because there's nothing to talk about, they just use them, like in any Java program. You're over thinking this here.
The 3 jar idiom: war, ejb, lib is one I've used over the years because it separates the 3 concerns, and limits dependencies. Client -> lib -> EJB. It also simplifies the build, since clients typically need just the lib jar and java. In the Netbeans IDE, this is trivial to manage. With minor work, it's straightforward in other IDEs or even in ant/maven. It's not a huge burden, but keeps the 3 parts relatively clean.
Dependency and Jar management is the nightmare of any large Java project, and even more so with EJB when you're dealing with the different deployable artifacts. Anything that can help mitigate that is a win, in my book, and truth is, a clean, stand alone lib jar helps a lot, especially of you need to integrate and use that lib with other code. For example, if you later write an external GUI client using Remote EJBs, or even web services, the lib jar is the only dependency that client has. The benefits of this jar far outweigh the minor pain it takes to set up this kind of library.
In the end the lib jar is just a jar like any other jar you'd want to use in your application (like logging or any other popular 3rd party jars).

Concurrent access causes ClassCastException (X cannot be cast to X), or how to resolve such class loading problems in JBoss

I have a problem concerning JBoss and class loading.
Here is the configuration I am working with. I have two instances of JBoss 4.2.3.GA on the same server. On each instance an application is running, and these applications are communicating with each other. There is an utility class, packed in both applications archives. This utility class is strictly the same in both applications.
This usually works fine, but in particular situations, I get ClassCastException. The case is the following:
A user is using a web application, which calls the application on the first JBoss instance (let's call it the application A). And application A calls the application B (on the second instance). This particular call takes several seconds to succeed.
If another user is trying to use the web application in a similar context (call to application A, which calls application B), and if this call happens during the first user call, I get systematically a ClassCastException : X cannot be cast to X (where X is my utility class, shared by both applications).
I found some information, and I deduced it was a class loading problem. Indeed, in this particular context of concurrent calls, my utility class is not loaded by the same class loader. I put a print command to see which class loader is used. In usual behavior, org.jboss.mx.loading.UnifiedClassLoader3 is used to load classes. In the particular described above, the application B seems to used a different class loader for the second user. My print command gave me the following:
WebappClassLoader
delegate: false
repositories:
/WEB-INF/classes/----------> Parent Classloader:java.net.FactoryURLClassLoader#de8209
My guess is that application B return an instance of my utility class loaded by this WebappClassLoader, and application A (which is using UnifiedClassLoader3) cannot cast it.
But i don't get why the UnifiedClassLoader3 cannot be used in this case, on application B. And why is this WebappClassLoader used ?
All I know about the class loading configuration in my JBoss instances is that class loading isolation is used, the following configuration is used for both applications :
<jboss-app>
<module-order>strict</module-order>
<loader-repository>applicationAorApplicationB.ear</loader-repository>
</jboss-app>
Do you have any advice to resolve this problem? How can I configure jboss class loader to avoid these class cast exception?
I precise that there is no hot deployment: I clean the server each time I deploy the applications.
If JBoss is using different classloaders for different packages, it is actually following the behavior according to the spec. For many releases it did not do this. You can disable WAR classloader isolation. See the JBoss documentation for more information.
You can also use a variety of different methods that do not require the applications to be in the same classloader for communication, and this would make your applications more specification compliant. See this stackoverflow question for more details.

Using the client jar in EJB 3 and design patterns

I'm new to EJB 3 and pretty confused with some doubts which Google didn't provide with a satisfactory answer.
I'm trying to create a framework with some base classes and some utility methods which my other applications can use. All applications are to be deployed on the same server.
When I'm trying to create a new EJB 3.0 project in eclipse, it asks if I want to create a client jar also. What purpose does this client jar serve? My ejbmodule is added as a part of the EAR file. So do I really need this client jar?
Do I need to create both local and remote interfaces? Or just remote interfaces will do?
I decided to keep all the interfaces in a project called projCommon and the bean definitions in projApps. The remote interfaces which the bean classes implement are in projCommon. So projApps is dependent on projCommon.
I plan to use a delegate method defined in projCommon to invoke the bean classes. That will mean that projCommon is also dependent on projApps, rt? And lead to a circular dependency.
How exactly are EJB's directly injected?
Would be really helpful if you can kindly provide an explanation to my doubts.
When I'm trying to create a new EJB
3.0 project in eclipse, it asks if I want to create a client jar also. What
purpose does this client jar serve?
An EJB client JAR file is an optional JAR file that can contain all the class files that a client program needs to use the client view of the enterprise beans that are contained in the EJB JAR file. If you decide not to create a client JAR file for an EJB module, all of the client interface classes will be in the EJB JAR file
My ejbmodule is added as a part of the
EAR file. So do I really need this
client jar?
You do not really need the EJB Client it just provides an easier packaging to use the EJBs from a client.
Do I need to create both local and
remote interfaces? Or just remote
interfaces will do?
If all your EJBs are in the same EAR then you can use local interfaces, if not you need remote interfaces. Local interfaces are more efficient, the calls are done be reference.
Some Containers (i.e. WebSphere) will optimize this at runtime for you and automatically call local interfaces if it is possible.
I decided to keep all the interfaces
in a project called projCommon and the
bean definitions in projApps. The
remote interfaces which the bean
classes implement are in projCommon.
So projApps is dependent on
projCommon.
I would keep my projects organized by functional areas. Make local calls within the functional areas and remote ones outside of the functional areas, This allows you to later split the functionality to be deployed on different servers to scale it. It also keeps the code more modular. This also avoids any circular dependencies.
How exactly are EJB's directly
injected?
The how it works does not matter, That is going to be done by the container. The whole point of J2EE is to abstract out the how.
As per http://www.developer.com/print.php/3650661:
EJB 3 containers provide the facilities to inject various types of resources into stateless session beans. Typically, in order to perform user tasks or process requests from client applications, the business methods in the session bean require one or more types of resources. These resources can be other session beans, data sources, or message queues.
The resources that the stateless session bean is trying to use can be injected using annotations or deployment descriptors. Resources can be acquired by annotation of instance variables or annotation of the setter methods.
See here for more details. Hope this help.

Categories

Resources