I'm trying to write a plugin into a framework application (Joget). My plugin source looks something like this:
public class MyPlugin extends ExtDefaultPlugin implements ApplicationPlugin, ParticipantPlugin {
...
public void execute(){
...
SecurityContextImpl secContext = (SecurityContextImpl) WorkflowUtil.getHttpServletRequest().getSession().getAttribute("SPRING_SECURITY_CONTEXT");
}
}
When I run the plugin, I get the following exception.
java.lang.ClassCastException: org.springframework.security.context.SecurityContextImpl cannot be cast to org.springframework.security.context.SecurityContextImpl
I'm using Maven. Now since both have the same package name, I'm assuming I'm accidentally using the wrong package version in my plugin JAR (that contains the SecurityContextImpl class) than the one in the framework. But I've double-checked and it looks like I'm including the correct one in my plugin package.
Is there a way to see the classloader or source JAR of my class (e.g. using reflection in some manner)? Any other ideas on how to address this?
This type of java.lang.ClassCastException, where both classes names are equals, occur when the same class, or two class with the same name are loaded by 2 different classloaders.
I don't know Joget, but you are talking about plugin. Frameworks often load plugins in separate classloaders to ensure a proper isolation between them.
Since you say I've double-checked and it looks like I'm including the correct one in my plugin package., you may want to remove spring-security from your package, as it's probably already loaded by the framework classloader.
You're using Maven, so you may simply add <scope>provided</scope> to the spring-security dependency (but not sure, since we don't have your pom.xml)
I've got the same exception when I was running my plugin.
There are two cases in general:
1. The class is a local class.
And that is to say, there is no repository(groupId, artificateId, etc) to be deployed in the pom.xml of your plugin. The solution is, go the target folder and open the xxx-0.0.1-snapshot.jar file, then open META-INF/MANIFEST.MF, add the source file of that class /dependency/file.jar, then add the source jar to the dependency folder
Remarks: It is better to give a version of the your local file and add it as shown in your pom.xml to let it be found as src in your code.
<!-- your source jar need to be renamed as example-1.0.0.jar -->
<dependency>
<groupId>this.should.be.the.prefix.of.your.package</groupID>
<artificateId>file.name<artificateId>
<version>1.0.0</version>
<systemPath>${basedir}/lib/stclient_updated-1.0.0.jar</systemPath>
<scope>system</scope>
</dependency>
2. The class is a remote class with repository
I had this type of problem once because the repository is not correct, see also Maven Repository to find the official repository of the source.
I hope that it could help =)
Cheers
Related
I've included a .jar in my maven project writing this in pom.xml:
<dependencies>
<dependency>
<groupId>org.loopingdoge.acme.model</groupId>
<artifactId>acme-model</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${basedir}/src/main/webapp/WEB-INF/lib/acme-model.jar</systemPath>
</dependency>
</dependencies>
acme-model.jar contains org.loopingdoge.acme.model.House but this cast
public class HouseAdder implements JavaDelegate {
public void execute(DelegateExecution delegateExecution) throws Exception {
House house = (House) delegateExecution.getVariable("house");
}
}
gives me this error when deployed on a Wildfly server:
18:50:20,255 ERROR [org.camunda.bpm.engine.context] (default task-45) ENGINE-16004 Exception while closing command context:
org.loopingdoge.acme.model.House cannot be cast to org.loopingdoge.acme.model.House: java.lang.ClassCastException: org.loopingdoge.acme.model.House cannot be cast to org.loopingdoge.acme.model.House
at org.loopingdoge.acme.services.HouseAdder.execute(HouseAdder.java:13)
Such cases happens when a class will be loaded over different classloaders. java make them distinct even if package and classname are identical.
You need to find out on which ways this class will be loaded. As first step, find the jars which contains that class.
or/and read this on SO
Ran into the same problem. Further analysis showed that two different class loaders were used, as stated in this thread already. In my case the culprit was devtools of spring boot, a tool which likely many will have active in their pom. Seems that devtools doesn't play well with (in my case) camunda java delegates with embedded camunda engine.
I guess that you have the class in multiple places, e.g. packaged the jar within WildFly and the WAR you deploy. Check that you have the class only one time on the classpath.
By the way: Better not use system dependencies if not absolutely necessary. This is what maven repositories are for.
If I check my effective pom I will find the following entry:
<dependency>
<groupId>com.package.of.other.department</groupId>
<artifactId>someArtifact</artifactId>
<version>2.4.2</version>
<scope>provided</scope>
</dependency>
This comes from the parent pom that we have to use to let our software (bpmn processes) run on a company wide platform.
Now comes a hacky part. There will be a bigger change and we cannot use someArtifact anymore. Unfortunately that artifact gets called directly by all our processes (you design the process and configure the full qualified class name for an item) and can't just configure a different artifact, as that would most likely break a lot of the running processes.
The simple plan was to create a class with the same package name and with the same class name, remove every dependency to the original package and everything should work fine. During the tests I noticed that it doesn't use my new class but still the original one, most likely because it gets provided as dependency via the mandatory parent pom and for some reason prefers that over my local one.
Excluding a provided dependency from the parent pom doesn't seem to work that easily?! Any idea how I could solve my issue?
If the application is regular java, the class that will be load is the first class met in the classpath order.
If you use other runtime package dependency management, the strategy is different. As example you can adjust your import-package in OSGi to ensure the use a class contains in private-package.
In my current project I used Guava Cache to cache something with expiration, but when actually call this interface, it had below error
Caused by: java.lang.NoSuchMethodError: com.google.common.base.Platform.systemNanoTime()J
at com.google.common.base.Ticker$1.read(Ticker.java:64)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2225)
And the reason is that there are two Platform in the classpath
one in Gauva, one in google-collections:jar
And LocalCache of Guava uses Paltform of google-collections causes this error. I have some question about this, why not Class in the same jar has higher priority? why not randomly choose one, but always use Platform of google-collections?
Yes it is possible that two jars include the same class name. It happens when you import for example two jars of different versions of the same library.
If you import dependencies using maven for example when you import a library it can import dependencies of other libraries causing this kind of problem. In this case you need to explicit that when you import a library you need to exclude a secondary dependency. This is done with the exclusions tag.
You can force priority by specifying classpath order. Java look for class in jars in order that is pecifyed in classpath.
In case you using maven and ide to run you have no control over order of classpath, but you can exclude dependee module from classpath.
<dependency>
<groupId>some</groupId>
<artifactId>id1</artifactId>
<version>1.0.0.0</version>
<exclusions>
<exclusion>
<groupId>another</groupId>
<artifactId>id2</artifactId>
</exclusion>
</exclusions>
</dependency>
In this case id2 will not be in your classpath anymore.
class loading priority will depends on the ClassLoader, you can find lot of articles about java class loading. if you are trying to run a standalone java application probably class loading will be done by URLClassLoader.
in this case all urls(jar file locations or classes) given in the -cp or -classpath will be added as URLs to the URLClassLoader, then when application needs to load a class this URLClassLoader will iterate through its URLs and once it found the class it will be loaded.
so everything depends on the class path order.
NOTE: but in some context class loading is not simple as this. ex: jboss-module class loader.
I have some Java code that is currently packaged in the BEA Workshop for WebLogic Platform.
My task is to migrate the structure of the project (without actually touching the code) to a maven structure to be packaged from command line (or from eclipse m2e).
Problem is, the code has some annotations like this:
#WebService(serviceName = "Cancelacion", targetNamespace =
"http://www.banamex.com.mx/OtorgamientoPension/cancelacion")
#WLHttpTransport(contextPath = "OtorgamientoPension", serviceUri =
"cancelacion", portName = "cancelacionSOAP")
#Policies({
#Policy(uri="policy:Wssp1.2-Wss1.0-X509-Basic256.xml", direction = Policy.Direction.inbound),
})
public class CancelacionPortImpl implements CancelacionPort {
...
}
That create some configuration inside the war (a mysterious meta-inf inside the web-inf and plenty of xml).
Please notice the #Policies which is from a WebLogic library. It creates some security-related config and that's (alongside the ws stuff) is what i want to generate.
Is there a way to process this from maven?
EDIT
So far I have tried with the weblogic-maven-plugin. It didn't work (also, due to internal policies, the not-so-straightforward way of installing this plugin is not an option).
I'm trying to find a vague reference a co-worker gave me about certain "jtools" compiler... but can't find anything that comes with that name and have some relation with WebLogic.
So the #Policies annotation is still a problem.
Right now I'm looking for a eclipse-plugin that does this, based on the premise that was the IDE who process that annotations.
For the wsdl issue, I find out that the namespace definition whas wrong. I corrected it and now it's working. I used the jaxb2-maven-plugin because I have no knowledge of jaxws-maven-plugin and I already had the config of the former.
Looks like you might need some Weblogic classes on your classpath. Short of uploading these to your own private Maven repository, you might consider checking out the Oracle Maven repository to find the Weblogic artifacts you need. Since these are likely container-provided jars (i.e. you don't need to package them in your war), you'll want to define them with a scope of "provided" in your dependencies, e.g. <scope>provided</scope>.
I am trying to follow this SO question which uses a Jetty ServletTester class.
I have spent all morning trying to locate the JAR that houses ServletTester to no avail. Even pulling down the aggregated "all JAR" doesn't turn up a *.testing package with that class in it. See for yourself, do a Maven/Gradle resolve for:
compile 'org.eclipse.jetty.aggregate:jetty-all-server:8.1.14.v20131031'
Even in their source code on GitHub it looks like there isn't a testing subproject, yet, in those JavaDocs above, it seems to exists somewhere...
Does anybody know where I can find the JAR that houses this class? If so, what is it, where/how do I acquire this JAR, and what did you do to figure this out (so I don't need to ask these types of questions again!)?
According to Maven Central, this class can be found in org.eclipse.jetty:test-jetty-servlet:8.1.16.v20140903:jar
Add the following dependency:
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-servlet</artifactId>
<version>8.1.16.v20140903</version>
</dependency>
Also, you can use sites like Maven Central's find artifact by class name feature.