Specifying a custom path of beans.xml for CDI - java

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.

Related

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.

Packaging a Java EE Application

I have an Enterprise project (EAR) with one EJB and several web modules, these web modules have lots of classes in common, they are exactly the same for each project, so if I modify one of them I'll have to manually copy the code to the other projects as well. I don't want to put them in my EJB module because they use a lot of front-end related resources.
Is there a way to share these classes between the web projects?
Obs: They also use classes and resources from the EJB module.
Make another module with all commun classes and package it as a Jar. Then add the jar as a dependency to the other project.
Maven should be a good tool for this project.
There is no way to have shared classes outside of a .war which are capable of having web-specific resources injected.
I would refactor the common classes into a separate .jar. You could make them EJBs, or just regular classes. Either way, you won't be able to inject web-specific resources; the classes in .wars will have to pass such things as method parameters. In the case of EJBs, you can't directly pass non-serializable objects like HttpServletRequests; I don't know if that will create a significant impediment.
An EJB .jar can be placed anywhere in the .ear, but if you choose to make a non-EJB .jar, it can be placed in the lib directory of your .ear file. It's also a good place for EJB interfaces, if you aren't writing no-interface EJBs. From the Java EE specification's "Application Assembly and Deployment" chapter:
A .ear file may contain a directory that contains libraries packaged in JAR files. The library-directory element of the .ear file’s deployment descriptor contains the name of this directory. If a library-directory element isn’t specified, or if the .ear file does not contain a deployment descriptor, the directory named lib is used. An empty library-directory element may be used to specify that there is no library directory.
All files in this directory (but not subdirectories) with a .jar extension must be made available to all components packaged in the EAR file, including application clients. These libraries may reference other libraries, either bundled with the application or installed separately, using any of the techniques described herein.

Difference between JARs and EJB JARs from a usage perspective

When I use Tomcat,
the common utilities are packaged as JARs in tomcat/lib
because every WAR has its own class loader,
and classes and libs under the WEB-INF/lib directoy of the WAR is not visible to other ones.
When I use Jboss,
the common utilities can packaged not only as JARs in jboss/lib but also as EJB JARs (invoked as services)
When I have some classes as common services, I can put them in JARs as well as EJB JARs.
I have no idea about the difference between JARs and EJB JARs from a usage perspective.
Can anyone guide me to the right path?
The difference is clear when you see the difference between the contents of a JAR vs a EJB JAR. Apart from the source files (compiled) and the manifest that a JAR file has, you'd also need the following (back in the pre-annotation days):
The XML deployment descriptor
The beans
The remote and home interfaces
Dependencies
This tells the container which are the EJBs and their home/remote interfaces so when a request asks for a bean, the container will know which one to invoke. Without these files, there is no way of you telling the containers (except annotations wherever applicable), that this the bean implementing an interface.
More information can be found at this url

How can I define a different target folder for some dependencies in Maven

I run many instances of the same web application under Tomcat and to save memory I copy some of the libraries to Tomcat's lib (tomcat\lib) and shared (tomcat\shared) folders. Libraries that go under lib can be found by both Tomcat and web applications, libraries that go under the shared-folder can only be used by web applications. My web application also need some libraries on the web application level so those libraries goes under WEB-INF\lib.
I have defined in my pom.xml that most libraries have a scope of provided so that they're not copied to WEB-INF\lib, however is there any way to define that I would like some libraries to go under a custom-defined folder; e.g. WEB-INF\lib\tomcat\shared and WEB-INF\lib\tomcat\lib, from where I could mover them manually to Tomcat's corresponding folders on the server?
That is not really the recommended way to package dependencies, as usually the web application would be deployed without furhter modification of the war file.
I think you can archieve what you want using the dependency:copy-dependencies goal, but it would require some configuration. You would have to set includeScope to provided, set the correct outputDirectory and then define the artifacts with the includeGroupIds or includeArtifactIds options.
Make a separate maven project which contains the war file and define the dependencies which should be located in the share-folder as scope: provided. Furthermore create an other separate module which has these dependencies and create an appropriate archive from it via maven-assembly-plugin...

Using spring beans from other modules?

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.

Categories

Resources