What is the use of converting jars to bundles in WAB(OSGI)? - osgi

After exploring the OSGi framework, I had developed a sample web application.The Web Application Bundle(.war or .jar) is packaged inside an eba.
The war file contains a bunch of embedded jar files in its WEB-INF/lib
directory.These jars have been converted to OSGi bundles(using maven-bundle-plugin) with the required export and import packages as per the relation between the jars.
Now I have to even mention all these jars(WEB-INF/lib) in the bundle-classpath.
The above works because a bundle(wab is also a bundle) can include one or more jarfiles within it, and use a Bundle-Classpath manifest.mf entry to point to them.
Incase I dont include the jars in the bundle-classpath I get a ClassNotFoundException.
The question is,then there's no point converting the jars to osgi bundles.Obviously all the jars in the WEB-INF/lib are loaded by the same class loader(i.e wab's class loader) ,so then we are not reaping the major benefits of OSGi which is mainly a per bundle classloader concept?

Putting jars inside the WEB-INF/lib is the old-style normal-java way of handling dependencies, and putting them outside the war is the new-style OSGi way of handling them.
By packaging your war's dependencies in WEB-INF/lib, you're treating them as normal jars (remember a bundle is also a jar). So in that case, you're right that there wasn't much point in using bundles.
One of the benefits of using wabs instead of wars is to get away from the dreaded 100 Mb monolithic war. Rather than packaging the bundles inside WEB-INF/lib, try having the war import the packages it needs using Import-Package:, and package the dependencies inside the eba. (If you don't remember to have the war import the packages it needs, you'll get the class not found exceptions you were seeing, because the OSGi container won't know your war needs those packages.)

Related

Classloading problem in multimodule maven application

I have multimodule maven application. Inside the main directory where parent pom resides I have some modules. I am in the process of adding another one on the same level as the other modules. The application is packages as EAR and deployed into Websphere, this EAR is configured to use shared library which basically is a directory containing jars. In this shared library Apache Crimson resides which is used by some of the modules. I am adding the new module based on Spring Framework 4.0.0.RELEASE. The whole project is a legacy and uses Java 6 and Hibernate 2.1 :( . The problem is that this Crimson make my new module crashing during deployment:
BeanDefinitionStoreException: Parser configuration exception parsing
XML from ServletContext resource [/WEB-INF/spring/root-context.xml];
nested exception is javax.xml.parsers.ParserConfigurationException:
Unable to validate using XSD: Your JAXP provider
[org.apache.crimson.jaxp.DocumentBuilderFactoryImpl#706b4db8] does not
support XML Schema. Are you running on Java 1.4 with Apache Crimson?
Upgrade to Apache Xerces (or Java 1.5) for full XSD support.
So I added to my new module this:
`<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.6.2</version>
</dependency`
But application still takes crimson.jar from the shared library. I tried to exclude this crimson.jar from parent pom but still it is taken from shared library.
Crimson is required by some other modules being packaged as jars hence the crimson is present ar EAR/lib level.
Another try was to change classloader order to take jars from the new module first and then go upward in the hierarchy (my new war module then parent ear). But this gave me some other exception.
The question is - how being in WAR module inside EAR module not take the jar from the ear level (it was also included in EAR/lib) and take from the WAR level only?
If parent-last class loading in the WAR doesn't work (perhaps due to something else in the WAR that can't be safely run with that delegation pattern), then I'd recommend an isolated shared library associated with the WAR. In the WAS administrative console, create a shared library with a class path containing the parser jar(s) you need, select the "use an isolated class loader for this shared library" option, then associated that shared library with the web module that needs it.
Isolated shared libraries utilize parent-last class loading, but only for the jars in the library rather than for the entire EAR or WAR. Because of that, you can target it to only the jars that you really NEED to use that type of delegation. The isolated library should allow you to use Xerces in the WAR while still using Crimson in the EAR.

Configure manifest.mf classpath in ear

I have an ear application which has 3 modules:
web.war
services.jar(ejb)
domain.jar(ejb)
I worked with maven tutorial:tutorial
At the end author says about problems with manifest.mf in web module and suggesting some solutions. But this not worked for me. I think configuration is broken not only in that case. In my ear MANIFEST (classpath) i have also prefix "lib/" before services module(services are separated jar as ejb module in my app).
I saw i can use my specific prepared Manifest.mf, but i don't know how to configure it manually. Could I duplicate jars in my app modules? For example add domain.jar in services and web? Is it correct?
I have specific structure:
1.sample-ear with web and services module
2.sample-web with sample servlet(without dependencies from other project in code).
3.sample-services with dao classes(using entities)
4.sample-domain with entity beans
I tried modify manifests in every package, but I didn't find a solution. When i want to run my application on WildFly10 i get NoDefClassError (Class from domain.jar used in service.jar). Could anyone help to configure it?
On the other hand maybe you have better maven configuration in project and manually configuring the manifest.mf is not needed.

Maven ships dependencies inside war but not in jar

I have two maven projects, one (I will call it core) is an ejb-jar (ejb) and the other a war (client).
My client project consumes some ejbs inside my core...so far so good.
But I'm getting a ClassNotFoundException inside my core application because it can't find one class from apache-beanutils...I have set this dependency with compile scope in it's pom.xml but it does not get shipped inside the output jar.
When I check my client.war package I see every compile-scoped dependency inside the WEB-INF/lib folder...but in my core.jar I don't see any of it's dependencies...I'm totally confused about this.
Can someone help me? I tried to google it before asking but I didn't find anything useful so far..thanks.
You can use the maven assembly plugin to bundle all the jars in one super jar.
See this: question

Spring Rest Controllers: deployment to Tomcat

I want to develop a RESTful API within my multi-module Spring-based project using Spring Rest. For that purpose, I have a webapp module and some other business/data layer modules. For example, this would be my simplified project structure:
myProject
-- webapp (war-packaged)
-- business (jar-packaged)
-- data (jar-packaged)
Business module depends on data module and so does webapp on business module. Webapp imports successfully every module's application context. Now I want to be able to use some business module classes that do some kind of calculation according to some data retrieved from a DB in order to provide a certain resource. All examples I had a look at were quite simple and this multi-module approach was not covered at all.
What is the problem? As far as I am concerned, Tomcat loads classes in a certain order. Concretely, it first loads WEB-INF/classes and only then WEB-INF/lib (where all webapp dependencies are placed, business module in this case). So, there goes my question. Where should I place my Controller classes? If I place them within the webapp module I won't be able to autowire any business-module bean since Tomcat will throw a ClassNotFoundException when I deploy the webapp war (at least this is the behaviour I have experienced).
The answer is probably easy but I'm quite new to Spring and its world!
Thank you all in advance.
Your business and data jars would go into the WEB-INF/lib directory. Then those jars will automatically be added to the CLASSPATH for your app when you deploy it. You will need to deploy your application as a WAR file.
Ideally, you would build the business and data jars, add them to some repository, and then the build system would pull the proper version of each jar into the WEB-INF/lib directory for you.
And as to the original question, the controller classes go into the webapp/src directory.
Assuming you are using Maven 2. Make sure your assembly creator (e.g. maven war module) is including your dependent .jar files within the final .war file's WEB-INF/lib directory. This should be the default procedure (per: http://maven.apache.org/plugins/maven-war-plugin/war-mojo.html#dependentWarIncludes ). The other concern, then is whether your sub-projects (business and data) are even creating jars so that they could be included in the WAR output.
If you have doubts as to the contents of that war file, browse the listing of it by executing
'jar tvf $WAR_FILENAME' from the command line and by observing the WEB-INF/lib directory contents. You should see your business and data jars in there. Go further by exploding your war file, then browsing the contents of business and data jar (using 'jar xvf $FILENAME' to explode in a new directory).
Hope this helps!

Websphere 6.1 server

I have an issue in loading jars in websphere server. Some of the jars are present in WEB-INF/lib and some are present in local hard drive(ex., c:\lib folder). How can i load all these jars, during the startup of the application. If WEB-INF jars are loaded, external jars are not getting loading and viceversa..Need help on this....
WebSphere has a hierarchy of classloaders, parent classloaders cannot see child classloaders, hence you get surprises when you put different aspects of your application in different places.
Never attempt to place application jars in WebSphere's own lib directory, and never adjust WebSphere's own class path. There is ana rchitected way to make external jars visible, I'll explain that in a moment.
There are three places that you can put JAR files so that they will be loaded. By far the the best is simply to place the JARs in WEB-INF/lib. You can specify the search order preference PARENT LAST so that these take prececdence over jars supplied by websphere - but note that some fundamental jars cannot be over-ridden You cannot replace the IBM security for example.
Second you can add jars to the root of the EAR file. Noe that the hierarchy comes into play now, WEB-INF/lib jars can see EAR jars but EAR jars cannot see WEB-INF/lib jars.
Finally you can specify a WebSphere "Shared Libarary". See the Info Centre for how, it's very easy through the console. A shared library has a classpath, you add jars to that. Then you allocate the shared libarary to individual applicaitons or whole servers.
Once again You WEB app can see the shared library, but i don't beleive taht the convers is true. Hence putting framework code in a shread library may not work for you.

Resources