I have two distinct archives within in the same .ear deployed on an application server. One is a .war and one is a .jar. I have the same package names in both archives
in .jar archive>> com.me.dummy.MyClass
in .war archive>> com.me.dummy.CLientClass
In com.me.dummy.MyClass I have a protected method called proctectedMethod() . In com.me.dummy.CLientClass i invoke com.me.dummy.MyClass.proctectedMethod().
This does not cause any compile time issues, but at runtime it throws accessError
java.lang.IllegalAccessError
Why does this only throw the IllegalAccessError at runtime?
Thanks
I believe that this happens because your application server loads web application using separate class loader. You should consult your app server documentation how to make it to use the same class loader for whole enterprise application.
Related
When deploying a Springboot maven project(version 2.3.4.RELEASE) to an external Tomcat container,official guide says you need to mark the "spring-boot-starter-tomcat" dependency as provided ,but actually even if without doing that,the final war package which contains lib like "spring-boot-starter-tomcat","tomcat-embed-core" and "tomcat-embed-websocket" also works fine in tomcat8.5.54 or tomcat 9.0 ,so I am confused about that,"Do we really need set spring-boot-starter-tomcat as provided or not?" ,anyone could explains why?
"Traditional Deployment"
You don't want to have multiple versions of the same classes on the classpath. This can lead to many errors during runtime. For example, if you have a
public class MyServlet implements javax.servlet.Servlet
and you package both MyServlet.class and javax.servlet-api.jar (which contains javax.servlet.Servlet) into your application, you might get an error:
Servlet class MyServlet is not a javax.servlet.Servlet
What happens is: when the application classloader loads MyServlet, it looks for javax.servlet.Servlet in the application first and it finds it in javax.servlet-api.jar. The server compares this class with the one loaded by the server's classloader and concludes that they differ, since classes from different JARs are not equal. If the application is shipped without javax.servlet-api.jar this does not happen: the classloader does not find javax.servlet.Servlet in its own classpath, so it looks in the parent classloader.
Remark: This example can not actually be reproduced on Tomcat. Due probably to many incorrectly packaged applications the WebappClassLoader has an exception to the class loading rule: special classes such as those starting with javax.servlet or org.apache.tomcat are always loaded from the server's classloader (cf. the source code for a list of these exceptions).
TL;DR: due to the remark above, leaving spring-boot-starter-tomcat in the compile scope probably will do no harm, but it is a risk not worth taking.
I am trying to add metrics library to existing webservice on WAS 7. I am getting below error
Error 404: javax.servlet.UnavailableException: SRVE0203E: Servlet [AdminServlet]: com.yammer.metrics.reporting.AdminServlet was found, but is missing another required class. SRVE0206E: This error typically implies that the servlet was originally compiled with classes which cannot be located by the server. SRVE0187E: Check your class path to ensure that all classes required by the servlet are present.SRVE0210I: This problem can be debugged by recompiling the servlet using only the classes in the application's runtime class path SRVE0234I
What are the other run-time dependencies required for metrics-servlet-2.2.0?
I have metrics-core-2.2.0.jar and metrics-servlet-2.2.0.jar in my WEB-INF\lib folder.
Threads, ping and healthcheck servlets work fine.
I think your missing some more required jars, are you not using maven or gradle for dependency management
Please refer here to know all required jars that metrics-servlet-2.2.0.jar depends on. http://mvnrepository.com/artifact/com.yammer.metrics/metrics-servlets/3.0.0-BETA1
My suggestion is, it is always difficult to maintain dependencies without Maven/Gradle or any other build tools :).
I recently start a spring web project with HBase. The problem is,spring seems unable to resolve types under WEB-INF/libs. it complains about "unresolved org.apache.hadoop.conf.Configuration" which is indirectly referenced from required .class file, which is actually in a .jar under the WEB-INF/lib library. Is there anything to be set for spring container to find it?
You need to make sure that Spring itself was loaded by the same class loader: the WAR class loader. This class loader should include all JARs in WEB-INF/lib and all .class files in WEB-INF/classes.
There's a way to pass a class loader into Spring to use a different class loader than the one that loaded it (or the Thread's context class loader), but that gets more complicated.
OK I got the problem. It seems that my project depended on hadoop-core-1.0.2 whilst hbase depend on hadoop-core-1.0.0 and that confused Spring. I fixed the dependency and problem solved.
I am developing an application for WebSphere 6.1 which uses a Java servlet. Within my servlet, I have defined a serial vesion ID of 1L. Upon deploying and running my application, I am receiving a LinkageError of the following type (from the server log):
[5/9/11 15:14:26:868 EDT] 0000001c WebApp
E [Servlet Error]-[ManageRecordsConsumerServlet]: java.lang.Exception:
java.lang.LinkageError: LinkageError while defining class:
<redacted>.docindexupdate.batch.servlet.ManageRecordsConsumerServlet
Could not be defined due to: (<redacted>/docindexupdate/batch/servlet
/ManageRecordsConsumerServlet) class name must be a string at offset=2074
This is often caused by having a class defined at multiple
locations within the classloader hierarchy. Other potential causes
include compiling against an older or newer version of the class
that has an incompatible method signature.
I'm not sure what the issue is. I was seeing this previously before defining a serial version uid and figured that by defining that and being consistent, future updates to the class file would run successfully. There are no errors during compilation or deployment to the server. Is it possible that an older version of the servlet is cached somewhere on the WebSphere instance (I am only deploying on my dev machine at the moment)?
The
class name must be a string at offset=2074
line is also confusing.
I am suspecting you have a jar that is being loaded in two different classloaders. By that I mean, your websphere server on startup loads that jar or has an endorsed directory with that jar. Also your EAR you are deploying has that jar in its lib. The two can conflict at runtime
What I would suggest is to find out which jar ManageRecordsConsumerServlet belongs to and either remove it from your EAR lib or your Websphere endorsed lib (best would be your EAR lib).
It may be versioning, but I don't thing so.
When two classes loaded by different classloader, a ClassNotFoundException is normally thrown.
When a class is passed over a wire/loaded from disk cache, VersionMismatchException is normally thrown.
When a class with different method signatures is used, NoSuchMethodError or alike is thrown.
I think this case is a corrupted class file. Could be corrupted in cache or in the JAR.
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