Using spring beans from other modules? - java

I imagine this is simple - but I can't find the right combination of search terms to get an answer. If I have a multi-module application, how do I get the beans in module A available to the beans in module B.
The project setup looks a little like this:
project.ear/module-a.jar/resources/beans.xml
project.ear/module-a.jar/java/foo/bar.class
project.ear/module-b.war/java/foo/barFactory.class
The beans.xml isn't accessible by either classpath, or filesystem. Is there a way to do this? Or should I be doing everything differently?

Your appserver is likely using different classloaders for each module in your EAR, preventing one module from seeing resources in another. This is the default behaviour of JavaEE classloaders.
You either need to
reconfigure your appserver to use a "unified" classloader across the whole EAR (which is highly appserver-specific, but great if you can get it to work), or
package everything into one module (e.g. your WAR could contain everything), or
declare a formal manifest for the WAR module, allowing it to declare the its dependencies on the individual JAR modules, which should allow the WAR to see the resources in the JAR module.

I think there is an easier solution than these 3 skaffman mentioned above.
Put in a module-b.war/WEB-INF/web.xml these lines:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/resources/beans.xml
</param-value>
</context-param>
This enables loading every /resources/beans.xml from any piece of classpath (i.e. any jar on classpath) which is enough for you.
You should load a module-a.jar as a part of a module-b.war (module-a.jar resides in module-b.war/WEB-INF/lib location).
I have very similar granularity in my project: business-logic.jar with its beans' configuration and frontend.war which uses beans configured in previous one via ref="someBean". It works.

Related

Specifying a custom path of beans.xml for CDI

When I use Spring and want to write a unit test, I can specify a custom context configuration in various ways, for example, by providing a different path of the context.xml.
But I don't see the way how to do that for CDI if I want to use a custom dependencies configuration for testing in the same maven module.
The documentation is very strict about this point:
For EJB modules or JAR files, the beans.xml deployment descriptor, if
present, must be in the META-INF directory.
If there is already /META-INF/beans.xml in the sources, I can not place a different one into the test-resources (it simply will be ignored).
Is any way to configure Weld/CDI, may be by using some system variables, to change the path of the beans.xml?
For EJB modules or JAR files, the beans.xml deployment descriptor, if present, must be in the META-INF directory.
That is true, however that concerns an already created/packaged JAR which you then use as a dependency of your app. But your app can have it's own beans.xml too. beans.xml is just a means to define one bean archive and certain structures (interceptors, decorators, ...) within that archive. That means, for instance, that an interceptor enabled via beans.xml inside that JAR library will not be enabled in your application unless you specify it in beans.xml of that app too. Hence the link you see between the documentation and the testing you are asking about might not be correct/relevant. Not sure if I got you right there, though.
Is any way to configure Weld, may be through using some system variables, to change the path of the beans.xml?
No, there isn't. But in EE you mostly test with Arquillian and that allows you (among other things) to define a test deployment. There you can include any custom beans.xml you desire. That's also what Weld/CDI TCK tests use most of the time.

EJBs in libraries - Reusing EJBs

Let's say I want to create a library which I will use in future projects but I also want to include EJBs in that library referencing other EJBs etc.. That library would also contain simple java classes. What is the best way to do that? How do I define the dependencies in this case? I thought I would define them with annotations. If the user of the library wants to configure other dependencies he will be able to do so by overriding them inside the ejb-jar.xml of his project. Has anyone done something like this in the past? How would you go about it when developing in Eclipse?
Basically my problem is that as far as I can tell if I simply create an ejb-jar which I am going to include in all my projects the ejb container is going to instantiate my e.g. MDBs at deployment time even if I don't need all of the MDBs that are contained inside my library but only some of them.
Is a solution to not define MDBs as EJBs with annotations or inside the ejb-jar.xml but only their dependencies?
What about the session beans? Will they be automatically instantiated even if I don't use them inside a project?
EAR files. Although not very common, you could include your library and its dependencies in an EAR file and distribute that.
What I'd like to do is to distribute the library in its own Jar file along with a documentation of dependencies (e.g.: a Maven' POM file or ivy's xml file). Either way, you'll need a dependency manager.
There is also an option to build a fat JAR file in which all the dependencies are exploded. I don't really like that. If I have to include dependencies, I'd go with EAR files.

Resources shared by two projects in java

I have two projects that share some resources, some of these resources are images, property files ... I wonder how I can get the two projects to access these resources without duplicating them.
I am working with the eclipse IDE, I just want to refer to them to avoid duplication.
The projects are two web applications, my only development framework is JSF.
By default, the resource handling mechanism introduced in JSF 2.0 looks up resource in the following locations:
In /resources under the web application root folder.
In /META-INF/resources in JAR files.
You can set another resource folder inside your context root (wich by way is inside your project and you can't point to an external resource) by adding
<context-param>
<param-name>
javax.faces.WEBAPP_RESOURCES_DIRECTORY
</param-name>
<param-value>/path/to/resource</param-value>
</context-param>
to your web.xml, but i wrote this only for educational purpouses because you can't leave the scope of your app folder.
So your only viable option is to "cook" your own jar with your images and property files added in /META-INF/resources. Then add your jar as an external jar to your project and you are good to go.
IMHO you should use Maven, this is what I use to manage projects dependencies. You would either need to put the resources into one of the projects or create a separate project (jar) that both can share.

Where to put a shared library in JBoss AS 7

I have multiple web applications each using spring-hibernate and other open source libraries and portlets, so basically now each war file includes those jar files. How do I move these jars to a common location so that I don't have to put these in each war file? My jars are places in D:/ directory.
I tried creating modules but no success. e.g. if I added jar
<resources>
<resource-root path="mylib.jar"/>
</resources>
and mylib.jar needs another ABC class. That ABC class is in my WAR class-path. Here I get exception while loading this module. mylib.jar could not find ABC class and throws exception.
If those libraries are reused in several applications, probably the best solution would be to create JBoss modules.
For example, OJDBC library is used in several projects I'm developing. So, I added a new module to JBoss 7: https://community.jboss.org/wiki/CreateAModuleForOracleDatasourceInJBoss711Final (it's just an example).
But you said, that you tried creating modules, but with no luck. What was the problem? Did you get some errors?
EDIT
Answer updated in connection with updated question.
So, if I understood correctly, we can divide your libraries into two categories:
First category is "standard libraries": Spring, Hibernate, Log4j etc. So, these libraries might be added as modules into JBoss AS and reused in every WAR (scope=provided in Maven's dependency).
Any other non-standard libraries (i.e. written by yourself) might be added as modules as well. If these libraries require some other dependencies - these dependencies must be listed in module's XML file, as described in: https://docs.jboss.org/author/display/MODULES/Module+descriptors
Hope this helps at least a bit :)

JBoss - War library dependencies

I am trying to add some dependencies jar files. But these files when put in lib/endorsed or in WEB_INF/lib.jar results in startup error for jboss instances. I suppose this is happening because flat classloader structure of JBoss. If somebody has implemented the classloader settings in jboss-web.xml
<class-loading>
<loader-repository>com.example:archive=unique-archive-name</loader-repository>
</class-loading>
Can somebody give me a real life example ?
Also where should I place these jar files - lib/endorsed of jboss, or lib folder in deploy folder or in WEB_INF/lib
Duffymo's directive on not putting jars in endorsed is ignored at your peril.
In some additional detail:
Placing libraries in your WEB-INF/lib is a best practice for portability and consistency as it adheres to a standard provision for creating self-sufficient and distributable web archives, but you need to pay close attention to the class-loading declaration you're putting in your jboss-web.xml.
Assume a simple scenario without the class-loading declaration and a fictional example.jar:
If you place example.jar in WEB-INF/lib and it does not also exist in jboss//lib, then example.jar will only be visible to that specific WAR.
If you place example.jar in WEB-INF/lib and it does also exist in jboss//lib, the instance in WEB-INF/lib will essentially be ignored and the WAR will use the JBoss server instance's unified class loader to load the example classes from jboss//lib/example.jar. (The same would apply to any other WARs or EARs in the same server instance, assuming no class-loading overrides.)
The class-loading declaration is necessary in cases (such as) where you have two different versions of example.jar:
- jboss//lib: example1.0.jar
- WEB-INF/lib: example2.0.jar
In this case, JBoss will create a unique and isolated classloader for your WAR which will avoid jboss//lib/example1.0.jar in favour of WEB-INF/lib/example2.0.jar in the context of your WAR.
In summary, if you're only running one WAR in the jboss server instance and/or you have no conflicting JAR issues, ditch the class-loading declaration and put your JARs in jboss//lib. It makes the WAR file more lightweight, overall deployment may be simpler and you will not consume additional memory with extra class versions during hot-deploys.
They belong in the WEB-INF/lib directory of your WAR file. Don't put things in the endorsed folder.

Categories

Resources