WebSphere 8.5: unit testing & embeddable container - java

I'm trying to run the following unit test in a Maven project using a WebSphere 8.5 embeddable container:
import javax.ejb.embeddable.EJBContainer;
...
private EJBContainer ec;
#Before
public void setUp() {
final Map<String, Object> properties = new HashMap<String, Object>();
properties.put(EJBContainer.PROVIDER, "com.ibm.websphere.ejbcontainer.EmbeddableContainerProvider");
ec = EJBContainer.createEJBContainer(properties);
}
#Test
public void test1(){
...
}
But I'm getting the following exception in the setup method:
CNTR9403E: The embeddable enterprise bean container cannot start
multiple modules with the same file name: project1\target\classes and
project2\target\classes
Does anybody know how to get around this issue? I searched but couldn't find anything useful.
Edit:
I've found the documentation for the exception CNTR9403E here:
http://pic.dhe.ibm.com/infocenter/wasinfo/v8r5/index.jsp?topic=%2Fcom.ibm.websphere.messages.doc%2Fcom.ibm.ejs.container.container.html
CNTR9403E: The embeddable enterprise bean container cannot start
multiple modules with the same file name: {0} and {1}
Explanation User code has directed the embeddable container to start multiple modules with the same file name.
Action Specify a list of modules that does not have duplicate file names, or rename one of the modules with a unique file name.
But I don't see how I can fix this. Is it complaining about the two "classes" directories at the end of the paths? How can I solve this in a Maven multi-module project? Or is it a bug in WebSphere 8.5?

Yes, the classes directory name is causing the conflict. There is no workaround for using those directory names, so I would recommend testing the generated .jar instead, though I have no expertise with Maven, so I don't know how feasible that is. This is somewhat unsatisfactory, so you could open a WebSphere RFE to allow properties to be specified to disambiguate.

Related

Nested modules with Spring

I am developing project with Spring Framework.
I have created about 5 modules, sometimes one depend on other, but they are all on top level, and up to this point everything works fine.
Example:
Database module has only external dependencies
Identity module depends on database module
Facebook stuff module depends on identity module
Now, I have created directory in root of project called modules, and moved all modules into it (so they all were, and still are on same relative distance to each other).
All tests passes and I can build/compile and inspect classes without any problem.
However, now when I try to run only identity module (that does not require facebook stuff) spring throws me an exception, that it cannot find facebook beans. Of course it cannot, because there is no dependency, but I do not want to add this dependency. #Configuration is #Lazy so there is no point creating such #Bean anyway.
Code:
new AnnotationConfigApplicationContext(Application.class);
Application class is #Lazy #Configuration and does #ComponentScan from whole application, and as I understand it finds also #Configuration's from other modules and then - I do not know why - tried to create those #Bean's from other modules but fails as expected.
I have verified with git, that the only between working and not working states are moving those modules into new folder.
So to clarify, working/default structure is:
/.gradle
/.idea
/DatabaseModule
/IdentityModule
/FacebookModule
/.out
/.gitignore
and not working one is:
/.gradle
/.idea
/modules/DatabaseModule
/modules/IdentityModule
/modules/FacebookModule
/.out
/.gitignore
Code stays the same.
I think, that if I will add all dependencies to all modules then it will work but for obvious reasons I do not want to do this.
Am I doing something wrong?
Is there any convention, that I am breaking?
Bonus question: how are nested modules different, from ordinary folder containing modules?
EDIT:
I should also note, that all tests pass in both scenarios, however I am not using spring in tests (no dependency injection) - just new or Mock() everything

Spring dependency injection from webapp to external jars

I am integrating Java Plugin Framework within a Spring based web application (XML-free).
Everything is fine, except for the dependency injection in plugin context
For instance I have a data source I would like to use in a plugin without having to go back to property files by using #Autowired like for the rest of the application
I cannot find a way to do this except by using getBean, which I read was not the best practise on this subject.
I also had a look at LogicalDoc but this project resorts to properties reloading which is not the correct solution for me as I want beans attributes modifications to be available without further glue.
Does anyone know of an existing open source project where both these environment are used ?
Not being able to inject dependencies in plugins, I finally added the following methods to mother class of all plugins
public void setContext(ApplicationContextProvider a_ctx) {
m_theContext = a_ctx;
}
public ApplicationContext getApplicationContext() {
return m_theContext.getApplicationContext();
}
And retreive the beans from within the plugin by
getApplicationContext().getBean(*ClassType*)

Set the JAXB context factory initialization class to be used

I have updated our projects (Java EE based running on Websphere 8.5) to use a new release of a company internal framework (and Ejb 3.x deployment descriptors rather than the 2.x ones). Since then my integration Tests fail with the following exception:
[java.lang.ClassNotFoundException: com.ibm.xml.xlxp2.jaxb.JAXBContextFactory]
I can build the application with the previous framework release and everything works fine.
While debugging i noticed that within the ContextFinder (javax.xml.bind) there are two different behaviours:
Previous Version (Everything works just fine): None of the different places brings up a factory class so the default factory class gets loaded which is com.sun.xml.internal.bind.v2.ContextFactory (defined as String constant within the class).
Upgraded Version (ClassNotFound): There is a resource "META-INF/services/javax.xml.bind.JAXBContext" beeing loaded successfully and the first line read makes the ContextFinder attempt to load "com.ibm.xml.xlxp2.jaxb.JAXBContextFactory" which causes the error.
I now have two questions:
What sort is that resource? Because inside our EAR there is two WARs and none of those two contains a folder services in its
META-INF directory.
Where could that value be from otherwise? Because a filediff showed me no new or changed properties files.
No need to say i am going to read all about the JAXB configuration possibilities but if you have first insights on what could have gone wrong or help me out with that resource (is it a real file i have to look for?) id appreciate a lot. Many Thanks!
EDIT (according to comments Input/Questions):
Out of curiosity, does your framework include JAXB JARs? Did the old version of your framework include jaxb.properties?
Indeed (i am a bit surprised) the framework has a customized eclipselink-2.4.1-.jar inside the EAR that includes both a JAXB implementation and a jaxb.properties file that shows the following entry in both versions (the one that finds the factory as well as in the one that throws the exception):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
I think this is has nothing to do with the current issue since the jar stayed exactly the same in both EARs (the one that runs/ the one with the expection)
It's also not clear to me why the old version of the framework was ever selecting the com.sun implementation
There is a class javax.xml.bind.ContextFinder which is responsible for initializing the JAXBContextFactory. This class searches various placess for the existance of a jaxb.properties file or a "javax.xml.bind.JAXBContext" resource. If ALL of those places dont show up which Context Factory to use there is a deault factory loaded which is hardcoded in the class itself:
private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory";
Now back to my problem:
Building with the previous version of the framework (and EJB 2.x deployment descriptors) everything works fine). While debugging i can see that there is no configuration found and thatfore above mentioned default factory is loaded.
Building with the new version of the framework (and EJB 3.x deployment descriptors so i can deploy) ONLY A TESTCASE fails but the rest of the functionality works (like i can send requests to our webservice and they dont trigger any errors). While debugging i can see that there is a configuration found. This resource is named "META-INF/services/javax.xml.bind.JAXBContext". Here are the most important lines of how this resource leads to the attempt to load 'com.ibm.xml.xlxp2.jaxb.JAXBContextFactory' which then throws the ClassNotFoundException. This is simplified source of the mentioned javax.xml.bind.ContextFinder class:
URL resourceURL = ClassLoader.getSystemResource("META-INF/services/javax.xml.bind.JAXBContext");
BufferedReader r = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "UTF-8"));
String factoryClassName = r.readLine().trim();
The field factoryClassName now has the value 'com.ibm.xml.xlxp2.jaxb.JAXBContextFactory'
Because this has become a super lager question i will also add a bounty :)
I will work the entire day on this and let you know if there is any news.
Update/ Solution
This question has been solved. The original problem has occured because misconfiguration of complexly build multi model maven projects which one dependency used a updated version of a customized eclipse link jar that contained a definition for a JAXBFactory not available in the component where the error occured. Setting the JAXB context factory in most cases is configured with a jaxb.propertie file or JAXBContext file that contains the same definition. Detailed loading process of the appropriate JAXBContextFactory happens in javax.xml.bind.ContextFinder.
The error has not yet been solved (during the fact over 4 major EE/SE Applications lead to the error) and there is no general answer but that defined JAXBContextFactorys must exist in your classpath (wow what a wonder...) so you either have a that ClassNotFound Error because youre missing resources (well thats the acctual cause) or because you have a wrong JAXBContextFactory defined in any of the above mentioned propertie files which contain a definition according to the below answer.
Very many thanks for your great comments and support, i realy appreciate!
You can include a jaxb.properties file in the same package as your domain model to specify the JAXB (JSR-222) implementation you wish to use. For example it would look like the following to specify EclipseLink MOXy as your JAXB provider.
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
For More Information
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
Another quick and dirty solution (a workaround, really) that worked for me is to explicitly include a JAXB implementation to the maven build. For example
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.7</version>
</dependency>
Note that this adds a somehow unnecessary dependency to your build, as JAXB obviously already is part of each JRE >= version 6.
Most likely this will only work when the WAS classloader is set to parent last.

Spring Dependency Injection and Plugin Jar

I have web application running with a default impl of a backend service. One should be able to implement the interface and drop the jar into the plugins folder (which is not in the apps classpath). Once the server is restarted, the idea is to load the new jar into the classloader, and have it take part in dependency injection. I am using Spring DI using #Autowired. The new plugin service impl will have #Primary annotation. So given two impls of the interface, the primary should be loaded.
I got the jar loaded into the classloader and can invoke the impl manually. But I haven't been able to get to to participate in the Dependency Injection, and have it replace the default impl.
Here's a simplified example:
#Controller
public class MyController {
#Autowired
Service service;
}
//default.jar
#Service
DefaultService implements Service {
public void print() {
System.out.println("printing DefaultService.print()");
}
}
//plugin.jar not in classpath yet
#Service
#Primary
MyNewService implements Service {
public void print() {
System.out.println("printing MyNewService.print()");
}
}
//For lack of better place, I loaded the plugin jar from the ContextListener
public class PluginContextLoaderListener extends org.springframework.web.context.ContextLoaderListener {
#Override
protected void customizeContext(ServletContext servletContext,
ConfigurableWebApplicationContext wac) {
System.out.println("Init Plugin");
PluginManager pluginManager = PluginManagerFactory.createPluginManager("plugins");
pluginManager.init();
//Prints the MyNewService.print() method
Service service = (Service) pluginManager.getService("service");
service.print();
}
}
<listener>
<listener-class>com.plugin.PluginContextLoaderListener</listener-class>
</listener>
Even after I have loaded the jar into the classloader, DefaultService is still being injected as service. Any idea how I get the plugin jar to participate into the spring's DI lifecycle?
Edited:
To put it simply, I have a war file that has a few plugin jars in a plugins directory inside the war. Based on a value from a configuration file that the app looks at, when the app is started, I want to load that particular plugin jar and run the application with it. That way, I can distribute the war to anyone, and they can choose which plugin to run based on a config value without having to to repackage everything. This is the problem I am trying to solve.
It seems like all You need is to create the Spring ApplicationContext properly. I think it's possible without classpath mingling. What matters most are the locations of the Spring configuration files within the classpath. So put all Your plugin jar's into WEB-INF/lib and read on.
Let's start with the core module. We'll make it to create it's ApplicationContext from files located at classpath*:META-INF/spring/*-corecontext.xml.
Now we'll make all plugins to have their config files elsewhere. I.e. 'myplugin1' will have its config location like this: classpath*:META-INF/spring/*-myplugin1context.xml. And anotherplugin will have the configs at classpath*:META-INF/spring/*-anotherplugincontext.xml.
What You see is a convension. You can also use subdirectiries if You like:
core: classpath*:META-INF/spring/core/*.xml
myplugin1: classpath*:META-INF/spring/myplugin1/*.xml
anotherplugin: classpath*:META-INF/spring/anotherplugin/*.xml
What matters is that the locations have to be disjoint.
All that remains is to pass the right locations to the ApplicationContext creator. For web applications the right place for this would be to extend the ContextLoaderListener and override the method customizeContext(ServletContext, ConfigurableWebApplicationContext).
All that remains is to read Your config file (its location can be passed as servlet init parameter). Than You need to construct the list of config locations:
String locationPrefix = "classpath*:META-INF/spring/";
String locationSiffix = "/*.xml";
List<String> configLocations = new ArrayList<String>();
configLocations.add(locationPrefix + "core" + locationSiffix);
List<String> pluginsTurnedOn = getPluginsTurnedOnFromConfiguration();
for (String pluginName : pluginsTurnedOn) {
configLocations.add(locationPrefix + pluginName + locationSiffix);
}
applicationContext.setConfigLocations(configLocations.toArray(new String[configLocations.size()]));
This way You can easily manage what is and what is not loaded into Spring ApplicationContext.
Update:
To make it work there's one more hidden assumption I made that I'm about to explain now. The base package of the core module and each plugin should also be disjoint. That is i.e.:
com.mycompany.myapp.core
com.mycompany.myapp.myplugin1
com.mycompany.myapp.anotherplugin
This way each module can use <context:componet-scan /> (on equivalent in JavaConfig) easily to add classpath scanning for it's own classes only. The core module should not contain any package scanning of any plugin packages. The plugins should extend configuration of ApplicationContext to add their own packages to classpath scanning.
If you restart the server, I see no reason why you can't just add the JAR to the WEB-INF/lib and have it in the CLASSPATH. All the complication of a custom class loader and context listener goes away, because you treat it just like any other class under Spring's control.
If you do it this way because you don't want to open or modify a WAR, why not put it in the server /lib directory? Let the server class loader pick it up. This makes all plugin classes available to all deployed apps.
The answer depends on how important the separate /plugin directory is. If it's key to the solution, and you can't add the JAR to the server's /lib directory, then that's that. I've got nothing. But I think it'd be worthwhile to at least revisit the solution you have to make sure that it's the only way to accomplish what you want.

How to extend/customize a WAR with another project

We have the following scenario with our project:
A core web application packaged as a
war file (call it Core project).
The need to "customize" or "extend" the core app
per customer (call it Customer project). This mostly includes
new bean definitions (we're using
Spring), ie. replacing service
implementations in the core.war with
customer-specific implementations.
We want to develop the Core and Customer projects independently
When the Customer project is developed, we need to be able to run/debug it in Eclipse (on Tomcat) with the Core project as a dependency
When the Customer project is built, the resulting war file "includes" the core and customer projects. So this .war is the customer-specific version of the application
I'm looking for suggestions as to the best way to do this in terms of tooling and project configuration.
We're using Ant currently, but would like to avoid getting buried in more ant. Has anyone done this with Maven?
I've seen a lot of posts on how to build a web application that depends on a java application, but nothing on a web application depending on another web app.
Thanks!
Sounds like Maven WAR overlay does what you want.
In Eclipse there is a "native" WTP way to do this. It mainly using linked folders and a little hack in .settings/org.eclipse.wst.common.component file. You can read the article about it at http://www.informit.com/articles/article.aspx?p=759232&seqNum=3 the chapter called "Dividing a Web Module into Multiple Projects". The problem with this is that the linked folder must be relative to some path variable can be defined in Window/Preferences/General/Workspace/Linked Resources tab. Otherwise the linked folder definition (can be found in .project file in project root) will contain workstation specific path. The path variable practicly should be the workspace root. This solution works great with WTP, deploy and everything else works like it should.
The second solution is to use ant for it. Forget it. You will deeply regret it.
The third solution is to use maven for it. You can forget the comfort of WTP publishing if you dont do some tricks. Use war overlays like others suggested. Be sure to install both m2eclipse, m2eclipse extras. There is an extension plugin released recently, that can help you. Described at this blog. I did not try it, but looks ok. Anyway Maven have nothing to do with linked folders, so I think even the first solution and this maven overlay can live together if necessary.
As for headless builds you can use HeadlessEclipse for the first solution. It is dead (by me) now, but still works :). If you use the maven overlay + eclipse stuff, headless builds are covered by maven.
This is little bit more involved but at a high-level we do it as below. We have the core platform ui divided to multiple war modules based on the features (login-ui,catalog-mgmt-ui etc). Each of these core modules are customizable by the customer facing team.
We merge all of these modules during build time into 1 single war module. The merge rules are based on maven's assembly plugin.
You usually start from the Java source code. WARs don't include the Java source code, just the compiled classes under WEB-INF/classes or JARs under WEB-INF/libs.
What I would do is use Maven and start a brand new empty webapp project with it: http://maven.apache.org/guides/mini/guide-webapp.html
After you have the new empty project structure, copy the Java source code to it (src/main/java) and fill out the dependencies list in pom.xml.
Once you've done all this you can use mvn clean package to create a standard WAR file that you can deploy to Tomcat.
You might want to look into designing your core app with pluggable features based on interfaces.
For example say your core app has some concept of a User object and needs to provide support for common user based tasks. Create a UserStore interface;
public interface UserStore
{
public User validateUser(String username, String password) throws InvalidUserException;
public User getUser(String username);
public void addUser(User user);
public void deleteUser(User user);
public void updateUser(User user);
public List<User> listUsers();
}
You can then code your core app (logon logic, registration logic etc) against this interface. You might want to provide a default implementation of this interface in your core app, such as a DatabaseUserStore which would effectively be a DAO.
You then define the UserStore as a Spring bean and inject it where needed;
<bean id="userStore" class="com.mycorp.auth.DatabaseUserStore">
<constructor-arg ref="usersDataSource"/>
</bean>
This allows you to customise or extend the core app depending on specific customer's needs. If a customer wants to integrate the core app with their Active Directory server you write a LDAPUserStore class that implements your UserStore interface using LDAP. Configure it as a Spring bean and package the custom class as a dependant jar.
What you are left with is a core app which everyone uses, and a set of customer specific extensions that you can provide and sell seperately; heck, you can even have the customer write their own extensions.

Categories