I've added EclipseLink MOXy to my JavaFX-8 application, and since then the application does not start anymore. The error is: Could not find or load main class x.y.z. When I remove MOXy, then the application starts perfectly well. Of course then, the application doesn't use the MOXy implementation of JAXB.
The JavaFX application is packaged as a self executable jar. It includes a Weld implementation of CDI for JavaSE, and a Jersey implementation of jax-rs. I do have a jaxb.properties file in the package that contains my JAXB classes, and it does specify the JAXB context factory of MOXy.
So basically, I don't understand the reason why the application does not start anymore when MOXy is packaged within the application. Any clue?
Edit:
The problem may come from a jar file used as a dependency of MOXy that could be signed.
Ok, that's indeed a signature mismatch in the produced application JAR file.
I'm using maven to build the JavaFX application. In the build process, all the dependencies are unpacked during the package phase, and are then packed again in a single JAR file containing my application.
The unpack step is done with the maven dependency plugin. I had to add the following configuration to exclude all the signature files:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<excludes>META-INF/*.SF</excludes>
<excludes>META-INF/*.DSA</excludes>
<excludes>META-INF/*.RSA</excludes>
<excludeScope>system</excludeScope>
<excludeGroupIds>junit,org.mockito,org.hamcrest</excludeGroupIds>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Now it works.
Related
I have a maven project with this structure.
I want to use same jar in different EARs with different properties.
When I run "mvn install", it creates 2 EARs but it cannot do filtering with this config. How can I solve this issue?
With Maven, you cannot filter a file belonging to a JAR module which is already built.
Each module is built and packaged separately. So, if you JAR needs to have a property which the value is populated dynamically, I may propose you two solutions :
Put the properties file which contains the key-value for conf.path in each EARs and in the JAR side, you could use a helper class to lookup in the classpath the value associated to the conf.path key.
You can perform this processing when the value is required or as soon as the application has started up if you need it very soon.
Create two flavors of your JAR whose the property differs. In this case, the property information is not stored any longer in the EAR but directly in the JAR
Look at the classifier element :
The classifier allows to distinguish artifacts that were built from
the same POM but differ in their content. It is some optional and
arbitrary string that - if present - is appended to the artifact name
just after the version number. As a motivation for this element,
consider for example a project that offers an artifact targeting JRE
1.5 but at the same time also an artifact that still supports JRE 1.4. The first artifact could be equipped with the classifier jdk15 and the
second one with jdk14 such that clients can choose which one to use.
Another common use case for classifiers is the need to attach
secondary artifacts to the project's main artifact. If you browse the
Maven central repository, you will notice that the classifiers sources
and javadoc are used to deploy the project source code and API docs
along with the packaged class files.
To produce multiple jars, configure the maven-jar-plugin plugin in your build in this way :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>jarVersion2</classifier>
<includes>
<include>**/jarVersion2.properties</include>
</includes>
</configuration>
</execution>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>jarVersion1</classifier>
<includes>
<include>**/jarVersion1.properties</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
After you can reference in your WAR the jarVersion artifact like that for the war 1:
<dependency>
<groupId>groupIdOfTheJar</groupId>
<artifactId>artifactIdOfTheJar</artifactId>
<version>versionOfTheJar</version>
<classifier>jarVersion1</classifier>
</dependency>
And like that for the war 2 :
<dependency>
<groupId>groupIdOfTheJar</groupId>
<artifactId>artifactIdOfTheJar</artifactId>
<version>versionOfTheJar</version>
<classifier>jarVersion2</classifier>
</dependency>
Im working on Moskito integration with a web app (non maven project).
**
Maven Project No Issue:(its working good)
**
Im using annotation (AOP) to monitor a class/method. here when i add annotation on class/method level and compile a .java file it generates two .class files
example.. i have a class called Order.java. here if i keep #Monitor annotation and compile Order.java it generates two classes one is normal Order.class and other one is Order$Clause1.class
since i have added below plugin on pom.xml so its generationg additional .class files
*<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<aspectLibraries>
<aspectLibrary>
<groupId>net.anotheria</groupId>
<artifactId>moskito-aop</artifactId>
</aspectLibrary>
</aspectLibraries>
<source>1.6</source>
<target>1.6</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>*
BUT
**
Non Maven Project having Issue:
**
in non maven project the additional Order$Clause1.class is not generated on /classes folder. due to that im not able to monitor those class/methods on moskito application.
(even i have added AJDT plugin also on Eclipse and added all required jars as well. app runs good on moskito but only class/methods are not monitored on moskito)
How to do it/ generate additional .class files for moskito on a normal poject(non maven) ?
your ideas helps me, thank you.
Issue got resolved, by making maven project convert to aspectJ project
and then add moskito-aop jar to aspectJ compiler classpath. done
I am new to maven. I have created a maven project which will be packaged to JAR. I did clean package then jar is created. When i extracted the same jar, i could not see any dependencies (jars) i added in pom.xml inside the packaged jar. If i give this jar to third party clients how will the code work without any dependent jars ? Please help me how maven manages the jars?
Thanks!
Maven handles dependencies based on how you configure the dependency plugin.
See this reference for a simple example of how to do this.
In this example, the following code configures where your dependencies will end up:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>log4j</includeGroupIds>
<outputDirectory>${project.build.directory}/dependency-jars/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Then this code sets up the classpath for your main jar, which will allow anyone running it to find these dependencies
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.mkyong.core.App</mainClass>
<classpathPrefix>dependency-jars/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
Your other option would be to create a single jar, with all dependencies included, by following this example here
You could distribute the jar and the POM file if you want to try and provide your users with the files in that manner, but they'd need to be able to access your Maven repository where those dependencies are kept.
Core maven doesn't handle this. Maven is a build tool, its work is to build an artifact (a jar in your case). Dependencies you define in your module's pom.xml file are needed to get the code compiled. You'll need maven plugins to do so.
Now, you're asking not about the build, but the distribution of your compiled binaries.
If I understand it should be a lot of jars (your and your dependencies). Alternatively you may distribute the code as a jar + dependencies inside.
Example:
A first case:
If your code resides in module A (say, the code is in packages org.a.*) and depends on some thirdparty (say, log4j, whose classes reside in org.apache.log4j) than you can expect that you jar will only contain the classes of module a and you expect that the log4j will be added by the user of your module automatically (The first case).
A second case:
module a.jar will contain both org.a.* and org.apache.log4j.* classes, everything in the same module.
In general the first approach is more "healthy" and in this case you shouldn't do anything in maven. Maybe your distribution tool/documentation should contain this information.
If someone uses the module a in his/her code like a thirdparty (if you develop a framework or something) and if his/her project is mavenized, than the fact you've defined a dependency on log4j will make the maven to download the log4j as well as your a.jar (In maven notation, this is called "transitive dependencies").
If you're interested in the second case (this can be relevant if you define some "client application", like "jndi client for some server" for example) you might want to take a look on Maven shade plugin
Beware this can lead to dependency hell (what if the application that uses your client also makes use of log4j? what if the log4j-s are of different version)/
Bottom line, you probably want the first approach, think twice before you decide the second approach :)
One more tip, if you just want to download all the dependencies of your module "a" you might want to use maven dependency plugin - type the following in the command prompt
mvn dependency:copy-dependencies
and you'll find all the dependencies in target/dependencies folder
Hope this helps and happy mavening
The simplest solution to the problem is to use the maven-assembly-plugin which can create such jar with dependencies like the following:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>distro-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Afterwards you can distribute the created jar xyz-1.0-jar-with-dependencies which contains the defined dependencies.
If you need more control on how the resulting artifact is created or if some files needed to be overwritten etc. you might take a deeper look into maven-shade-plugin
I have a Maven-based project, in which I trying to add some JAXB classes automatically generated by the "jaxb2-maven-plugin" Maven plugin. However, my first cut has me in a circular dependency loop:
Because these JAXB classes aren't generated yet, my other sources which reference them have compilation errors.
Because those other sources have compilation errors, these JAXB classes don't get generated.
It seems like there are two obvious possibilities for solving this:
Comment-out the broken references, so that the project builds and the JAXB classes are automatically generated. Then copy those generated sources from /target into /src/main/java, so that references to them won't cause compilation errors.
Create an entirely separate project, consisting of nothing but the JAXB stuff. Include it as a dependency in my main project.
Am I missing something here? Option #1 seems flat-out ridiculous... that just can't be the manner in which people use JAXB. Option #2 seems more rational, but still rather inefficient and cumbersome. I really have to take on the overhead of an entirely separate project just to use JAXB?
Are there any more elegant approaches that developers use to reference JAXB-generated classes in the same project where the Maven plugin generates them?
UPDATE: By request, here is the relevant portion of my POM:
<build>
<plugins>
<plugin>
<!-- configure the compiler to compile to Java 1.6 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- The name of your generated source package -->
<packageName>com.mypackage</packageName>
</configuration>
</plugin>
</plugins>
</build>
When I run mvn clean package, I DO see my JAXB sources being generated beneath the /target subdirectory. However, those generated sources are not being automatically added to the classpath for the compile phase.
POST-RESOLUTION UPDATE: It turns out that my compilation issues had more to do with the fact that I was running in Eclipse, and its Maven integration has some issues with "jaxb2-maven-plugin". See this StackOverflow question for more detail on that issue and its resolution.
How did you configure your jaxb maven plugin? Normally it runs in the generate-sources lifecycle, which comes before the compile lifecycle. So your JAXB generated classes should already be there when your own code gets compiled, Maven puts them in target/generated-source and puts that folder on the classpath.
Edit:
This is my code we use at work (and which works as expected):
<plugin>
<groupId>com.sun.tools.xjc.maven2</groupId>
<artifactId>maven-jaxb-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>src/main/resources/<companyname>/xsd</schemaDirectory>
<includeSchemas>
<includeSchema>retrieval.xsd</includeSchema>
<includeSchema>storage.xsd</includeSchema>
</includeSchemas>
</configuration>
</plugin>
Apparently we use yet another jaxb plugin... (see also this thread: Difference of Maven JAXB plugins).
i would suggest you to split jaxb-generated classes (api) and your BL classes (implementation) to 2 maven projects with separate pom.xml for each, and the main root pom.xml with the compilation order. that way, you will be able to build api.jar, then maven will install it inside the local repo, and after that you can use it as the dependency of your implementation. so it will looks like:
-API\
--pom.xml - for api, jaxb generation
-IMPL\
--pom.xml - for impl, api dependency is here
pom.xml - main pom.xml with references to the projects above
Maybe try using the maven-jaxb2-plugin instead:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.2</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
The answer from dfuse is correct, though. Either plugin should generate sources before compiling, and the result of the source generation will be on the classpath. I tested this with both plugins. Is it possible for you to post your schema, or at least the schema for the type that your code is failing to pick up on the classpath?
I'm using proguard with a spring mvc application and maven.
My pom.xml's build section looks like:
<build>
<finalName>myapp</finalName>
<plugins>
<plugin>
<groupId>com.pyx4me</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<obfuscate>true</obfuscate>
<!--<options>-->
<!--<option>-keep public class</option>-->
<!--</options>-->
<injar>${project.build.finalName}</injar>
<injar>${project.build.finalName}</injar>
<inFilter>com.myapp.*</inFilter>
</configuration>
</plugin>
</plugins>
I also tried:
<injar>${project.build.finalName}.war</injar>
When I run:
mvn clean install
Build failure message:
[proguard] Reading program war [/Users/me/dev/git/myproject/myapp/target/myapp.war] (filtered)
[proguard] Error: The input doesn't contain any classes. Did you specify the proper '-injars' options?
ERROR] Failed to execute goal com.pyx4me:proguard-maven-plugin:2.0.4:proguard (default) on project myapp: Obfuscation failed (result=1) -> [Help 1]
It seems to have picked up my jar correctly as the messages before show:
[INFO] --- proguard-maven-plugin:2.0.4:proguard (default) # myapp ---
[INFO] execute ProGuard [-injars, '/Users/me/dev/gitserver/myproject/myapp/target/myapp.war'(!META-INF/maven/**,com.myapp.*), -outjars, '/Users/me/dev/git/myproject/myapp/target/myapp_pg.war', -libraryjars, ....
Also, what options do you suggest I use? This is a spring mvc so I have annotations like:
#Autowired
#Service
#Repository
#Controller
So any of those classes/fields should not be renamed I would imagine.
(My goal is just to make it a headache to someone who decompiles, such that they can't just decompile and use the code. Obfuscating will let them use it, but they won't be able to maintain the codebase unless they re-write it. I don't have any fancy algorithms so I have nothing really to hide in that respect.)
Update
Let me be clear here, my spring mvc using maven for some reason (I'm new to maven) when doing a mvn clean install produces both a myapp.war file and a exploded war myapp/ (this is what I want to deploy in production, not the myapp.war file)
My myapp folder has:
/target/myapp/
/target/myapp/meta-inf (empty folder)
/target/myapp/web-inf
/target/myapp/web-inf/classes (com.myapp. ...)
/target/myapp/web-inf/lib/
/target/myapp/web-inf/ web.xml, application.xml (for spring)
/target/myapp/web-inf/views/
So proguard should be obfuscating in the /target/myapp/web-inf/classes folder right?
How do I tell it to do so?
Update 2
I'm getting this now:
OK, I am not getting: failed to execute goal ...proguard .. Can't rename /Users/me/dev/git/project1/myapp/target/myapp/web-inf/classes (see my updates section for what I changed in my pom.xml)
I changed my pom.xml with:
<configuration>
<obfuscate>true</obfuscate>
<injar>${project.build.finalName}/WEB-INF/classes/</injar>
<inFilter>com/myapp/**</inFilter>
</configuration>
ProGuard filters work on file names, so
.....(!META-INF/maven/**,com.myapp.*)
probably won't match any class files. You probably want
.....(!META-INF/maven/**,com/myapp/**)
See ProGuard manual > Usage > File Filters
Can you post your entire pom?
Normally, Maven compiles to /target/classes (Even for WAR files) and the WAR plugin does the copy to web-inf/classes right before the package phase. You should not be manually compiling classes to web-inf/lib with Maven.
EDIT: OK this has take quite a bit of research, but I've found an answer for you. First, according to the ProGuard documentation, you should not have ANY classes in your war project:
Notably, class files that are in the WEB-INF/classes directory in a
war should be packaged in a jar and put in the WEB-INF/lib directory
You need to refactor your project so your web classes are built in a separate jar. Once you have built that jar project, you must add it as a dependency in your war project.
Once I created that setup, I was successfully able to build a war project with the following configuration:
<build>
<plugins>
<plugin>
<groupId>com.pyx4me</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<inFilter>com/example/**</inFilter>
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jsse.jar</lib>
</libs>
<options>
<option>-keep class com.example.echo.EchoServlet</option>
<option>-injar ${project.build.directory}/${project.build.finalName}.${project.packaging}</option>
<option>-outjar ${project.build.directory}/${project.build.finalName}-proguarded.${project.packaging}</option>
</options>
</configuration>
</plugin>
</plugins>
</build>
Note the "com.example.echo.EchoServlet". Since progaurd was going to change the name of my classes, I had to "keep" this servlet name so I could reference it in the WAR project's web.xml. If you use annotation based servlet configuration, I imagine this won't be necessary.