Bundle Manifest dependencies - eclipse-plugin

Recently I have been assigned to improve the structure of inter-dependencies that an Eclipse plugin has. Let's call it "core" and assume that the following manifest describes this eclipse plug-in where all the other plug-ins point to in order for them to access services (RMI, OSGi services). These services are reachable by using either "rmiservices.jar" (Maven generated artifact) and another eclipse plug-in called "org.osgiservice". Other bundles reference "core" bundle and use the Export-Package declaration in order to use these services.
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: core
Bundle-SymbolicName: coreid;singleton:=true
Bundle-Version: 0.0.1
Bundle-Activator: org.sample.Activator
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Export-Package: org.sample.api,
org.rmiservice,
org.osgiservice
Bundle-Localization: plugin
Bundle-ClassPath: lib/rmiservices.jar
Require-Bundle: org.osgiservice;bundle-version="1.0.0";visibility:=reexport
Questions that arise in order to improve the dependency structure are:
The "core" plug-in includes within its generated jar the rmiservices.jar. Would it be better having rmiservices.jar as a separate bundle instead?
rmiservices.jar is a maven generated artifact. Would there be a benefit moving it to a P2 repository and expose it inside a target definition?

You should put the jar into its own bundle. If your application grows, you might need to access that library from different bundles. With local jars you risk different versions being loaded by different bundles (due to those local jar copies), leading to very strange errors at runtime.
If the jar is available in P2, then you can easily build your complete application using Tycho. The automation and reproducability of the build process is well worth the shortly longer build time.

Related

How to add a bundle manifest to an existing maven dependency?

I am using the Adobe XMP Core dependency within a maven file
<dependency>
<groupId>com.adobe.xmp</groupId>
<artifactId>xmpcore</artifactId>
<version>5.1.2</version>
</dependency>
The MANIFEST.MF of that bundle is not suited for osgi deployment, as no bundle specific information was provided. So I would need to add the following lines to that Manifest.mf
Bundle-ClassPath: .
Bundle-Version: 5.1.2
Bundle-Name: xmpcore
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.adobe.xmp.xmpcore
Export-Package:
com.adobe.xmp;version="5.1.2",
com.adobe.xmp.impl;version="5.1.2",
com.adobe.xmp.impl.xpath;version="5.1.2",
Is there a way of unpacking this maven artefact and exchanging the provided manifest via the maven dependency plugin or any different way?
For runtime enhancement use the Pax URL Wrap Project. If you have this bundle in your environment add the wrap: url-schema to your bundle installation it will auto-wrap your bundle on the fly.
IIRC, Eclipse Virgo Bundlor can do that work for you.
http://www.eclipse.org/virgo/documentation/bundlor-documentation-1.1.1.RELEASE/docs/user-guide/htmlsingle/user-guide.html#usage.command.line
Virgo Bundlor will add all export-Package statements + all import statements which he can find via declared import-statements in your java-files. If the jar uses dynamic classloading, you need to add a template.mf file with the additional import.

Classloading issues in JBoss AS7

JBoss AS7 Developer Guide mentions the following classloading preference from a higher priority to lower priority:
1. System Dependencies - These are dependencies that are added to the module automatically by the container, including the Java EE api's.
2. User Dependencies - These are dependencies that are added through jboss-deployment-structure.xml or through the Dependencies: manifest entry.
3. Local Resource - Class files packaged up inside the deployment itself, e.g. class files from WEB-INF/classes or WEB-INF/lib of a war.
4. Inter deployment dependencies - These are dependencies on other deployments in an ear deployment. This can include classes in an ear's lib directory, or classes defined in other ejb jars.
However, I do not understand the DIFFERENCE between #2 and #3. What kind of dependencies could be classified under category 2 above vs category 3. To me, they look the same.
As an example of migrating my Spring application from JBoss 4 to JBoss 7, I encountered a NoClassDefError for quartz 1.6 jar that our application had been using. The quartz 1.6 jar is right inside the WEB-INF/lib folder of my application. This means it correctly falls under Category 3 above. But most articles on web indicate that I have to put it in either as a JBoss 7 module or define it in the jboss-deployment-structure.xml. Why ???
I have also read the migration guidelines and did the TattleTale exercise as pointed in those guidelines. But don't quite get it on what do I do with the report? I read the answer to this Best Practice for loading 3rd party JARs in JBoss AS7 standalone deployment? - looks like quite some amount of effort will be required for the migration. Does not seem like a quick trivial task considering the numerous dependencies an application can easily have. Can someone please confirm this?
I guess I need a guideline about
For which jars do I create a module.xml? (Possible candidates -
Spring, Quartz, Apache , C3P0 connection pools etc) ???
For which jars do I have a jboss-deployment-structure.xml? (What
could be good candidates here?)
For which jars do I leave them in web-inf/lib folder? (Application
uses certain specialized math libraries - like colt.jar, excel
graphing libraries like - jxls.jar, poi.jar - these seem like good
candidates here).
JBoss AS releases used to manage their set of libraries in different ways. Earlier, Release 4.x was used to define the core server
libraries into the JBOSS_HOME/server libraries. Thereafter, each server definition had its specific library into the server//lib folder.
JBoss AS 7 follows a real modular approach deprecating all earlier approaches. The server bootstrap libraries are now located at the root of the application server. There you can find the jboss-modules.jar archive, which is all you need to bootstrap the new application server kernel, based on the JBoss modules.
For which jars do I create a module.xml? (Possible candidates -
Spring, Quartz, Apache , C3P0 connection pools etc) ???
If there are any dependency jars those could be created as modules and define in the module.xml. Also you need to defined the dependencies of the define library.
ex.
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="rezg.rezg-dto">
<dependencies>
<module name="org.apache.log4j" />
</dependencies>
<resources>
<resource-root path="rezg-dto-1.0.0.jar"/>
</resources>
</module>
Connection pool can be configured as a module and the procedure for installing a new module
requires copying the .jar libraries in the appropriate modules path and adding a
module.xml file, which declares the module and its dependencies.
For which jars do I have a jboss-deployment-structure.xml? (What could
be good candidates here?)
All the dependency jars should be defined in here. Also you can define either in the MANIFEST.MF or standalone.xml.
For which jars do I leave them in web-inf/lib folder? (Application
uses certain specialized math libraries - like colt.jar, excel
graphing libraries like - jxls.jar, poi.jar - these seem like good
candidates here).
If there are any jars which is used only in your ear or war then those could be defined in WEB-INF/lib.
However, it is recommend to use as modules.

Maven2: Possible to deploy depends on artifact classifier?

In fact I have 2 different problems, but I think they are kind of related:
I have an artifact, with an assembly descriptor set which will build an extra JAR (with extra classifier). By default, Maven2/3 will deploy the assembly generated together with the main artifact to remove Maven repository. Is there any way that I can deploy only the main artifact but not the assembly?
I have an artifact, in which I have jar plugin generate another artifact with different classifier (more specific, an EJB artifact, and I generate an client JAR). I want to deploy only the client JAR to Maven repo coz I think the main EJB artifact is not really going to be shared by other project. Is it possible to do so?
Thanks a lot
editied to provide more info:
The reason for avoiding deploy the EJB, is because the EJB main artifact is not going to be depended by other project except the containing project. The containing project will build a EAR (which contains the EJB), and normally we only need that build locally (by mvn package). However, the EJB client is something that we will deploy to our repo to let other project share when they need to communicate with our application.
Honestly it doesn't harm to deploy the EJB too, but I just want to see if I can save unnecessary waste of disk space on our repository.
Similarly, for deploying assembly, it is because the project is something we want to deploy to let other project to depends on. However, when building that project, we also have a separate assembly created on the same time (for example, an all-in-one executable jar) which we only need that built locally, and it is not something that other projects will depends on.
Turn off the 'attach' option to the assembly plugin. Then it won't be officially an artifact and it won't deploy; it will just lurk in the target directory, sulking that you don't love it as much as it's elder sibling and plot revenge.
Based on your first question i would like to know why do you create the supplemental assembly which is usually deployed as well as the main artifact. If you wan't to prevent you can put the creation of the assembly into a profile but this means you will not generate the supplemental artifact in your usual build only by activating the profile.

Glassfishv3 not adding jars in ear to the classpath

I have been working on this problem for one whole day but in vain without any effective solution.
I have an ear file packaged with an ejb and a handful of jar files (including hibernate and the other dependent jar files).The ejb is stateless and enabled as a web service.
The ear file has been packaged using maven and has the below structure
ear->projectrelatedejb.jar
->hibernate.jar
->otherdependent. jar
->META-INF/application.xml
->META-INF/manifest.mf
The application.xml and manifest file are automatically generated by maven when I do a package.
When I deploy this ear file on glassfish it gets deployed with the ejb methods being accessible using web services. However when accessing the application (using soapui),
the ejb methods that perform some database functionality using hibernate throw java.lang.NoClassDefFoundError for the hibernate api during runtime.
It is obvious from the error that the hibernate jars are not on the classpath during runtime but since the jars are within the ear Glassfish should have
added it to the application classpath.
I tried various options like adding the classpath entries to the manifest.mf during the package (by using the element addClasspath with the maven-ear-plugin) which didn't do any good.Also with Glassfish we cannot add the dependent jars as modules to the application.xml unless the jars are application client jars
(Glassfish wouldn't deploy the ear file if the application.xml has the dependent jars declared as modules).
I also tried placing the jars in the lib directory within the ear (which isn't actually required) and with the manifest Class-Path header referencing the jars in the lib directory which also didn't fix the problem.
The quick and dirty fix which I can do to get this working is to place the hibernate and the other the dependent jars in Glassfish's lib directory.However,this is a bad practice
and I am somewhat reluctant to do it.
I would really appreciate if someone can provide me with a working solution to this problem.I have gone through the net looking for this problem
but couldn't find any solution.
Wondering if its a bug with glassfish or does glassfish need something special to reference the jars in an ear.
Thanks in advance.
I found a similar problem which is discussed here: http://www.tricoder.net/blog/?p=59.
Simply put, try putting the libraries in EAR/lib directory and according to JEE5 spec, glassfish will add them to class path automatically.
I used Server Library option to deploy application JARs and it worked for me.
Right click on your EAR-> Properties -> Libraries-> Add Library -> Create -> give name and change type in Library Type to Server Libraries then add JARs that should be deployed and confirm.
I work with NetBeans 7.0.1 and GlassFish server 3.1
When you say you added classpath entries to manifest.mf, which manifest.mf do you refer to? The one in ear-root/META-INF/manifest.mf ? Try adding a META-INF/MANIFEST.MF to your ejb module with Class-Path entries!

Include one Maven assembly inside another?

My project generates 3/4 assemblies, 3 jars and 1 war.[I need to use assemblies itself]
I need to include 2 of these assembly jars into my war.
How can I ensure that before assembly war creation , other 2 jars are created ?
Please respond
You have three choices:
define all the assembly executions in one plugin configuration, and order them as needed.
See this answer for more details.
Define an earlier phase for your jar assemblies so that they have all been packaged before the war is packaged.
Move the jar content into separate projects and specify them as dependencies of the war project so they are packaged automatically. This is the "Maven way" of handling this. It would also allow you to potentially reuse the jars in other wars.
I'd recommend option 3 myself, but the other two should both work.