I experimented with webservices and jboss4 for the last couple of days, and I stumbled over the following problem:
I included this dependency in my pom.xml:
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-jaxws</artifactId>
<version>4.2.2</version>
</dependency>
As it turned out, this caused JBoss4 to fail with the error message
java.lang.IllegalStateException: Cannot find endpoint meta data
Until I added the tiny little line
<scope>provided</scope>
to the dependency. I now understand that this problem was caused by the fact, that JBoss4 brings this library himself, and that it is the double inclusion of the same library (probably 2 different versions) that caused this. But now, when I look into the JBoss lib folder I see the following files:
commons-codec.jar
commons-httpclient.jar
commons-logging.jar
concurrent.jar
endorsed
getopt.jar
jboss-common.jar
jboss-jmx.jar
jboss-system.jar
jboss-xml-binding.jar
log4j-boot.jar
How do I know which jars correspond to which maven artifact? How do I know for any of the million files in my .m2/repository folder which groupid, artifactid and version number they belong to?
All the jar files in provided/included by Jboss are not related to maven. They are there just for the sake for jboss it self to run. Other application who wants to run in the container need to provide they own sets of library. BUT, some time, some of the library provided by JBoss is enough for the application (since they will live on the same VM), so you dont need to provide your own. You use those provided library for your development purpose, and later, when you deploy, you dont include them in your deployment.
So, there are no telling which Jar, provided by JBOSS should relate to which artifactId or groupId or version in the maven repositories, unless for some hint on their names.
For example, if you see that Jboss brings "commons-codec.jar" with it. There are no telling that the jar comes from which artifactId or groupId or version in Maven. You may guess that "commons-codec" should be a name of some artifact. Sites like http://mvnrepository.com/ helps you to find what related maven artifact that may relate to the jar you are investigating.
The artefact name is always ${artifactId}-${version}.${type}
in your case : jboss-jaxws-4.2.2.jar.
You're just looking for it in the bad place, the lib folder you're talking about must be the one of the unified classloader, the library you're looking for must be loaded by the server classloader i.e. it must reside in JBOSS_HOME/modules
[edit]
Ferdinand Neman is right when he says that jboss is not related to maven. Dependencies declaration in pom just allows maven to build and package your project. The runtime behavior depends on your targeted environment, the only things to ensure is that your dependencies must be resolved during classloading whether because they are packaged with your project or provided by the runtime environment.
Anyway the jar jboss-jaxws-4.2.2.jar will necessary be present on your workstation (in the local maven repository) to allow class linkage during maven compilation, as the jar is marked as provided it will not be included in the resulting build artefact.
Maybe you find useful this maven command
mvn dependency:tree -Dverbose
It shows you jar dependencies, classified by group-artifact and it also represents dependencies between them as a tree.
Related
I have an old ant-based build I must move to be Maven-based for our new build system. This old build is based on many well known libraries (Apache commons, etc.) which pose no problem to Maven, but it uses also about a dozen JARs in a subdirectory that are less well known or not known at all (can't find any information on) that I must include statically.
I have chosen this approach for including these more static JARs that I cannot get from Maven the way one would normally get them:
<repository>
<id>Pile of misfit JARs</id>
<url>file://${basedir}/lib</url>
</repository>
However, when it comes to creating <dependency> statements for these misfits, in the case of most of the JARs all I have is knowledge of the Java package paths in the code. I don't know how to discover what to use as groupId and artifactId. I have looked inside these JARs; some do have good information in manifests, but others do not or have only partial information.
(Incidentally, to use the <repository> construction above, I have to make use of $ mvn install:install-file ... and name groupId, artifactId and version too in addition to what I put into <dependency> in order to make the local, in-project repository work.)
I'm very grateful for any suggestions!
I will provide few outline.
Apart from well known jar files like Apache commons etc, you have to look into Manifest.mf file inside the unidentified jar files. You will find some name, company name etc.
Then go to mvnrepository.com and search for the name or company name which you found from the unidentified jar files.
If you get the actual artifact detail from mvnrepository.com, you can include group id, artifact id etc in maven dependency.
How ever all the above approach is time consuming.
There is another approach to get rid of. If you have latest version of Artifactory. Upload the unidentified jar files into Artifactory, it will either identify the details or it will generate the group id, artifact id version etc. If you want, you can provide your own artifact details also.
You can also refer to link.
http://roufid.com/3-ways-to-add-local-jar-to-maven-project/
The easiest way is to upload those jars to your Maven repo with some fake groupIds/artifactIds/versions using Maven deploy plugin. In this case you will be 100% sure that your Maven build uses the very same jars as your Ant build. Though you will still need to try to find our actual versions if you need to upgrade to newer version.
My pom.xml has this dependency:
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
When I use the XMLSerializer it throws an exception: java.lang.NoClassDefFoundError: nu/xom/Node
If I run the class locally and add the JAR to my classpath, everything works as expected. I'm running this class as a Jenkins plugin so I don't expect to be manually defining classpath - I figured that's what Maven should be handling.
It's important to note that Jenkins plugins require me uploading an hpi file that is created from Maven. It is not running based on the output jar. If I go on Jenkins box and manually put the xom JAR into WEB-INF/libs, it works. But obviously that means this plugin wouldn't for other people, which is self-defeating.
Here is minimal code causing error: https://github.com/DaveStein/parser-sample
The Readme has exact repro steps.
Note on chosen answer
The PR to my sample repo got me most of the way to where I needed to be. I did have a few other issues that had to get resolved, but the JSONObject conflict was the core problem. I took out all GlobalConfiguration as Jesse's PR suggested. The only other issue that might concern a future viewer was some glitch when using xom as explicit dependency while also using a higher version than 1.626 for org.jenkins-ci.plugins at the time of this post.
Jenkins core bundles json-lib. (A forked copy, not that it matters for purposes of this question.) It does not bundle the optional dependency¹ XOM, whatever that is. When your plugin loads XmlSerializer.class, it gets defined by the class loader for Jenkins core, which then attempts to link against classes such as nu.xom.Node. Since this is not available in the defining loader of XmlSerializer—the Jenkins core class loader (more or less jenkins.war!/WEB-INF/lib/*.jar)—you get an error. The fact that a class by that name is accessible in your plugin class loader is of no import, excuse the pun.
If your plugin needs to use its own versions of classes which are normally bundled in Jenkins core and exposed to plugins implicitly, then it needs to not only bundle those JARs (a regular compile-scoped Maven dependency suffices for that purpose), but to also use the pluginFirstClassLoader option. Before attempting to do so, you had better understand Java class loading semantics thoroughly, or you will be lost in a maze of cryptic² ClassCastExceptions and LinkageErrors.
By the way the mvn hpi:run command normally used to test plugin code iteratively does not simulate a realistic class loading regime. So if you are using pluginFirstClassLoader or any other tricks in this space, always double-check the resulting class loading behavior by (re-)installing an *.hpi in a sample Jenkins instance, for example using /pluginManager/advanced, or the install-plugin CLI command. Judging by your description, you were already doing that (and perhaps unaware of hpi:run).
¹The original sin here is use of optional dependencies. json-lib should rather have defined a distinct artifact json-lib-xom with hard dependencies on json-lib and xom. That would ensure that any given class loader can either see XmlSerializer and its dependencies, or neither.
²No progress on JDK-6273389, alas. Marked as a duplicate, but what it is a duplicate of, I am not sure. Theoretically Java 9 modules make questions like this obsolete—by imposing such onerous restrictions that applications like Jenkins could not use that module system to begin with.
please google "noclassdeffounderror vs class not found" , this error means the class dependency is in fact found but is not available in run time.
Try these steps:
Run mvn clean package and mvn clean install
Check if your maven environment is correct and has latest jars
Check if the installed target project contains the required jars
Check if dependency type is selected as runtime and not only as
compile time in pom.xml
Here is an example of using runtime dependency:
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
My guess is that the local version of the XOM jar is not the same as the one that is used in your Maven version. To verify use the dependency:list Maven command to list out all your dependencies. Verify if the XOM dependency listed is the same version as the local jar.
Probably error on jenkins occurred while this dependency has been loaded for the first time and now it's considered as complete. Try to remove dependency from jenkins' maven local repository and re-run. That might help you
why use Maven when you have such quantity of local jars?
So we have a client that have a lot of private jars and custom jars.
For example commons-langMyCompanyCustom.jar which is commons-lang.jar with 10 more classes in it.
So on their environment we use 100% Maven without local dependencies.
But on our site we have the jars for development in Eclipse and have Maven build with the public ones, but we do not have permission to add their jars in our organizational repository.
So we want to use the Maven good things like: compile,test, build uber-jar, add static code analysis, generate java-docs, sources-jars etc. not to do this thinks one by one with the help of Eclipse.
So we have 70 jar some of them are public if I get the effective pom on their environment I found 50 of them in Maven Central, but the other 20 are as I called "custom" jars. I searched for decision of course but found this:
<dependency>
<groupId>sample</groupId>
<artifactId>com.sample</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/yourJar.jar</systemPath>
</dependency>
So for all 20 of them I have to add this in the development maven profile??
Is there a easy way like in Gradle where you can add all folder with its dependencies to the existing ones?
Also installing one by one in every developer's repo is not acceptable.
Please forget the system scope as mentioned before! Too problematic...
Ideally:
Ideally, all your developers have access to Repository Manager in your or their organization (if possible).
A central environment for your System Integration Testing, maybe?
Alternatively, you may have a central environment for testing where all the dependencies are provided. This approach can be used to simulate how a compilation would work as if it's in your client's environment. Plus you only setup jars once.
So on their environment we use 100% Maven without local dependencies.
But on our site we have the jars for development in Eclipse and have
Maven build with the public ones, but we do not have permission to add
their jars in our organizational repository.
According to what you're saying in the above-quoted excerpt I believe you want to have set in your build's pom.xml assuming that in the client setup the dependencies will be present.
Especially, as you indicate that the organization doesn't give you permission to add their jars in your repository, I would use the provided scope.
As stated in the Maven docs, the definition of a provided dependency is as followed:
This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
So basically you assume that these dependencies will be present at your client's setup. However, this has some limitations. Meaning you can build solutions independently but cannot test it locally because you won't have the dependencies on your workstation.
If you won't even have access to the jars to configure your central environment ask if your client can provide a DEV/SIT environment.
None of the above? Inherit a parent pom.
To avoid the whole constant copy-paste process for every single (related) project, maven has the tools to centralize dependency and plugin configurations, one of such is by inheriting the configuration of a parent pom. As is explaining in the following documentation it is quite simple:
First you create a project with just a pom.xml where you define everything you wish to centralize (watch out, certain items have slight differences in their constructs);
Use as property of packaging tag the option pom: <packaging>pom</packaging>;
In the pom's that have to inherit these configurations set the parent configuration tags in <parent> ... </parent> (documentation is very clear with this);
Now everytime you update any "global" pom configuration only the parent version has to be updated on every project. As a result of this, you only need to configure everything once.
You can also apply this together with the abovementioned solutions, this way combining to find a solution that fits best to your needs.
But there is a big Maven world out there, so I advise a good read in its doc's to further acknowledge your possibilities. I remembered these situations because I've been in a similar situation you seem to be now.
Good luck!
Another alternative is the project RepoTree.
This one creates a Maven repository directory (not a server) from another directory which contains just the .jars. In other words, it creates the necessary .pom files and directory structure. It takes into account only the precise information from metadata contained in the archives (MANIFEST.MF, pom.xml).
Utility to recursively install artifacts from a directory into a local
Maven repository Based on Aether 1.7
This is 5 years old, but still should work fine.
TL;DR: MavenHoe creates a Maven repository server (not a directory) which serves the artefacts from a directory, guessing what you ask for if needed. The purpose is to avoid complicated version synchronizing - it simply takes whatever is closest to the requested G:A:V.
I have moved the MavenHoe project, which almost got lost with the decline of Google Code, to Github. Therefore I put it here for availability in the form of a full answer:
One of the options you have when dealing with conditions like that is to take whatever comes in form of a directory with .jar's and treat it as a repository.
Some time ago I have written a tool for that purpose. My situation was that we were building JBoss EAP and recompiled every single dependency.
That resulted in thousands of .jars which were most often the same as their Central counterpart (plus security and bug fixes).
I needed the tests to run against these artifacts rather than the Central ones. However, the Maven coordinates were the same.
Therefore, I wrote this "Maven repository/proxy" which provided the artifact if it found something that could be it, and if not, it proxied the request to Central.
It can derive the G:A:V from three sources:
MANIFEST.MF
META-INF/.../pom.xml
Location of the file in the directory, in combination with a configuration file like this:
jboss-managed.jar org/jboss/man/ jboss-managed 2.1.0.SP1 jboss-managed-2.1.0.SP1.jar
getopt.jar gnu-getopt/ getopt 1.0.12-brew getopt-1.0.12-brew.jar
jboss-kernel.jar org/jboss/microcontainer/ jboss-kernel 2.0.6.GA jboss-kernel-2.0.6.GA.jar
jboss-logging-spi.jar org/jboss/logging/ jboss-logging-spi 2.1.0.GA jboss-logging-spi-2.1.0.GA.jar
...
The first column is the filename in the .zip; Then groupId (with either slashes or dots), artifactId, version, artifact file name, respectively.
Your 70 files would be listed in this file.
See more information at this page:
https://rawgit.com/OndraZizka/MavenHoe/master/docs/README.html
The project is available here.
Feel free to fork and push further, if you don't find anything better.
In my example below there seems to be a discrepancy / duplication in the required steps in OSGi resolution and Maven dependency support.
I have a jar which is dependent on a external 3rd party jar, in this case time4j.
<dependency>
<groupId>net.time4j</groupId>
<artifactId>time4j-core</artifactId>
<version>4.16</version>
</dependency>
I can then run my simple jar locally by importing the packages and running etc.
When importing into OSGi I have to ensure that this jar is imported first, often using the PAX Wrap Url.
This is ok for 1 jar dependency but what about when there are multiple dependencies. I could use a features.xml file to collect these jars but why? I've already specified them in my pom.xml.
It seems there should be a way for OSGi / Karaf to read the pom.xml dependencies and import these into the container using the PAX Wrap url when needed.
Have I missed something here?
Sorry but your expectations are not in sync with reality.
First of all Maven dependencies are build-time dependencies. That's why you declare dependencies you know to be available in the runtime as provided
<scope>provided</scope>
Neither OSGi nor Karaf can do anything about your build time dependencies.
BUT with OSGi you can make sure your build dependencies are also available in your runtime and don't interfere with other libraries that might be available.
That's why you need to declare your imports and exports etc.
Karaf does help you with some of the dependencies for example with feature files.
If you have a feature definition maven project, all of your compile scope dependencies can be included in one feature file.
BUT, the OSGi resolver only looks at the currently available bundles and nothing more, no connection what so ever to maven, if you want to have some sort of automagic resolving of external dependencies you need to make sure that you have
a) an OBR resolver enabled (this depends on the karaf version you are using, with 4.x it's already included) and
b) an OBR repository at hand, Karaf Cave would be the project to look for in that case, cause it can reside like a proxy on top of a maven repository.
I want to use Jmathplot.jar
I tried to put it as a dependency
<dependency>
<groupId>jmathplot</groupId>
<artifactId>jmathplot</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/jmathplot.jar</systemPath>
</dependency>
but when installing I get this error:
Some problems were encountered while building the effective model for com.NResearch:dable-start-tRisk:jar:0.1-SNAPSHOT
[WARNING] 'dependencies.dependency.systemPath' for jmathplot:jmathplot:jar should not point at files within the project directory, ${project.basedir}/lib/jmathplot.jar will be unresolvable by dependent projects # line 44, column 19
How can I get around this please?
EDIT1:
I cannot change Maven to include all dependent jars into a single jar. As this is uploaded to a web project.
"Dependent" is using your project, "dependency" is used by your project.
The real error here is that jmathplot.jar is in a folder that can really only reliably be found by your project. Even though your dependents know how to find your artifact in the local repository, they won't know where the sources are for your artifact, hence won't be able to find lib/jmathplot.jar. You can fix that by changing the systemPath to an absolute path. It can still be parametrized, but then please use properties rather than implicit properties (such as ${project.basedir}.
It'd be better to get rid of the systemPath dependency, by installing jmathplot into a company repository, so it can be used alike 'normal' artifacts. But that may not be a useful option if you have to distribute your artifact out of the reach of your company repository. It would even be better if jmathplot would just get deployed to the Maven central repository.
As a last resort you may choose to bundle the dependencies (not the dependents). You can do this:
Using the Maven Shade Plugin. It lets you choose which packages to include which may be useful to bundle only jmathplot (and not other dependencies).
Using the Maven Assembly Plugin. It has a predefined descriptor for "JAR with dependencies" which would fit your use case. You could create your own descriptor off of that example and set dependencySets.dependencySet.scope=system to only include the system dependencies that are giving you trouble.
Best way is to install your dependency on your local repository. To do this:
1) using project source, install to local repository using mvn install
2) if you don't have source code, install to local repository using this
hope it's help
nota: you are spamming around this question, do you ? (see here: JMathPlot what is the Maven dependency code please )