JEE6 war packing into several modules - jpa

I want to split parts of my WAR application into different JAR components.
Every JAR component contains JPA-Entities, EJBs & JSF-Composite-Components.
Example: extracting the user management (XHTMLs, EJBs, JPA-Entities) into an own jar.
At first everything looks working fine as long as I don't have to use an entityManager.
Problem:
In EJBs of JAR-files the entityManager will never be injected.
I'm using the #PersistenceContext annotation for injection.
I have a beans.xml in all META-INF folders and everything (excepted entityManager) is injected correctly. It doesn't even matter if I place a persistence.xml in all JAR-files or only in the WAR-file.
Does anybody have a glue how this can be done?
Where do I have to place the different configuration files (beans.xml, persistence.xml)?
Do I need an ejb-jar.xml file?
Is this possible at all?
Technology-Stack:
JBoss 6.1 / PrimeFaces 3.2 / Maven / EJB 3.1 / Hibernate / JTA / CDI

You need a persistence.xml file in every jar that contains entities.
Every such persistence xml should define a different persistence unit.
If you want one persistence unit to refer to entities define in a different persistence unit then you need to include it as jar-file entry in the persistence unit definition (see example below).
This works for us for a very similar stack JBoss 5.1 (and then 7)/ EJB3/ Hibernate, Maven, ...
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="PersistenceUnitA">
<jar-file>JarContainingOtherPersistenceUnit</jar-file>
<jta-data-source>java:/jboss-mysql-ds</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
</properties>
</persistence-unit>

Related

OpenJPA > Is it possible to define persistence xml file somewhere else than META-INF with name persistence.xml

I am a new OpenJPA 2.2.2 user. I noticed that the database configuration has to be defined in META-INF/persistence.xml. This sounds to be too inflexible. Moreover, I found from the OpenJPA 2.2.2 documentation:
The OpenJPA runtime includes a comprehensive system of configuration defaults and overrides:
OpenJPA first looks for an optional openjpa.xml resource. OpenJPA searches for this resource in each top-level directory of your CLASSPATH. OpenJPA will also find the resource if you place it within a META-INF directory in any top-level directory of the CLASSPATH. The openjpa.xml resource contains property settings in JPA's XML format.
You can customize the name or location of the above resource by specifying the correct resource path in the openjpa.properties System property.
On base the introduction above, it seems that the database configuration file name is only possible to be persistence.xml. Moreover, I tried to place it in the top-level directory of my CLASSPATH, i.e., not inside the META-INF directory, it didn't work at all! Is there is any way to define this database persistence xml more flexibly, say in somewhere else than META-INF and with other name than persistence.xml?
First, there is no replacement for persistence.xml (p.xml for short). This is needed no matter what. Furthermore, the location of this file is clearly defined in the JPA specification (e.g. see "8.2 Persistence Unit Packaging" in JPA 2.0 spec). You MUST follow those rules on packaging. OpenJPA first and foremost follows the rules of the spec in regards to this file and its settings. No JPA provider is going to ignore the rules w.r.t p.xml file.
The section of text you copy/pasted is from here in the OpenJPA documentation:
http://openjpa.apache.org/builds/2.2.2/apache-openjpa/docs/manual#ref_guide_conf_specify
As you can see, this section describes an optional file named openjpa.xml. This file does not replace a p.xml file! It adds to it. And as the documentation states, it is simply used to add properties. That is, you can not define your persistence unit here, the only thing you can define are properties (i.e. ). If you define a persistence unit here, it will not be used. As an example, lets look at this openjpa.xml file:
<?xml version="1.0"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="">
<properties>
<property name="openjpa.jdbc.Schema" value="MySchema" />
<property name="openjpa.jdbc.DBDictionary" value="db2" />
</properties>
</persistence-unit>
This file defines two properties. Notice that the persistence-unit name is blank. That is intentional because, as I mentioned above, we can't define a persistence unit in this file. Finally, you can place this file in the META-INF on your classpath, as mentioned in the documentation. If you put this at the same spot as your p.xml file it will be found. As an example, in my JSE JUnit test, I place it on my hard drive in the directory e:/openjpaConfig/META-INF/openjpa.xml. I then put a classpath entry in my JUnit test to point to the directory e:/openjpaConfig. The classpath could point to a jar which contains this file in its META-INF directory. In a Java EE environment, you could place the file in a .jar file and place the .jar file in the lib directory of an ear.

How to call separately deployed ejb3 on wildlfy

As long as my EJB is deployed inside the war of the app using it everything works fine, I only have to #Inject it, no xml, and no local or remote interfaces. The webapp is a Vaadin 7.5.6 app using vaadin-cdi.
When deploying the ejb as a separate jar, the web-app calling it fails with "Forbidden". I've annotated it with
#SecurityDomain("other")
#RolesAllowed({ "guest" })
However, still "Forbidden". Probably some config is needed in the webapp as well. All examples I've found so far mentions jndi-lookup, ejb-jar.xml, web.xml, jboss-ejb.xml, ejb interfaces and whatnot. Is it even possible to have the ejb deployed separately and accessible, while avoiding all this extra config? I'd like to break up my app so that I don't have to deploy everything each time I make changes to the gui, but if I have to revert to "old school" ejb config I'm not sure there is a point.
Using Wildfly 9.0.2, Java 8 and Maven.
Edit:
EJB : The Hello World EJB lives in a maven sub-project, it has jar-packaging. It has no xml-configuration and no local or remote interface. There is no usage of maven-ejb-plugin. The implementation looks like this:
import javax.ejb.Stateless;
#Stateless
public class ReceptionService {
public String welcome() {
return "Hello, Developer! No XML, No Configuration, and it works!";
}
}
There is also a number of real-world session beans that use JPA inside methods that look like this (below) so there might be some persistence and transaction issues popping up as well here, but not until the simple hello-world case is working. The hello-world-webapp does not include any of these EJBs, just the simple hello-world-EJB.
#Stateless
#TransactionManagement(value = TransactionManagementType.CONTAINER)
public class DealerSession {
private Logger logger = LoggerFactory.getLogger(DealerSession.class);
#PersistenceContext(unitName = "MyUnit")
protected EntityManager em;
#TransactionAttribute(REQUIRED)
public Long create(DealerUpdate update) {
notNull(update, "update"); // and so on ....
The persistence unit is defined in the EJB project, and it connects to an datasource in Wildfly. In the real-world-beans transactions are rolled back on failure.
WAR : This is a Vaadin 7 webapp. It simply looks like this:
#CDIUI("")
#Theme("valo")
public class WelcomePage extends UI {
#Inject
ReceptionService service;
#Override
protected void init(VaadinRequest request) {
setSizeFull();
String message = service.welcome();
Label label = new Label("this is the message: " + message);
setContent(new HorizontalLayout(label));
} ....
The EJB jar-file is referenced in the dependencies. So it is included, and everything works as if the EJB bean was just a .class-file in the war. This is very convenient, because there is almost no configuration involved. But as the real-world-project here grows, I'd like to split up the deployment, so that I do not have to deploy all EJBs as part of the war each time the gui is updated, because it slows down the development cycle.
The war project depends on vaadin-cdi 1.0.3 and vaadin-bom 7.5.6, and of course the jar with the EJB (which has jar and not ejb packaging). Also vaadin-maven-plugin, maven-resource-plugin and maven-war-plugin is used.
Both projects also use wildly-plugin 1.0.2.Final. and depend on java javaee-api 7.0.
NOW, my naïve attempt so far has been to change packaging of the EJB jar to "ejb", add maven-ejb-plugin, specify scope provided in the dependency in the pom file of the war-project, and deploy war and jar separately. So far there are no error-messages or warning, both are deployed. But access to the ejb is "Forbidden", there is an error message in the gui saying that, strangely not in the wildfly console. I've tried to add #SecurityDomain and #RolesAllowed annotations to the EJB (see above), but stuff has to be configured on the webapp as well. If it is so that CDI only will inject the EJB as a pojo anyway, or I have to add Local and/or Remote interfaces, perform JNDI-lookups, add lots of stuff to xml configuration files and so on, I can manage that, because there are sample apps and documentation for that, but also everything gets a lot more complicated, and I want to avoid that.
First of all your EJBs are not not injected as such, even if they are deployed with your WAR. This is because you don't declare interfaces. In this case you will at least have to annotate them with #LocalBean which declares the no-interface-view for the bean.
When you outsource the EJBs into a jar, CDI is not able to inject the bean isntances that would be produced by EJB (the proxies) but injects pojo instances instead. To avoid this you could create a producer field or method for each EJB in your WAR. Injecting the bean with CDI then calls the producer. This producer would have to do a specific JNDI lookup (java:global/...) to get the EJB bean instance.
Then, when deploying to wildfly, you will have to add a dependency from the WAR to the JAR since both deployments have separate class loaders and can't see each other. The dependency connects both class loaders so that the one of the WAR is able to load classes of the JAR.
You will only have to activate CDI for the WAR not the JAR in this case since the EJB instances are retrieved by explicit JNDI lookups.
The answer I have approved for my question might be the right one if you absolutely need to use cdi-injection. I never came as far as I got it working, though.
Instead I decided to try use the #EJB annotation, instead of #Inject. When I deploy my ejb (in a separate jar from my web-app, that lives in a war-file) Wildfly registers jndi-names and reports this in the console. One of the names is "java:global/template-service-1.0.0-SNAPSHOT/ReceptionService". Note the "global" scope.
The #EJB annotation has a parameter called mappedName. Injecting and using the ejb like this did the trick:
#EJB(mappedName = "java:global/template-service-1.0.0-SNAPSHOT/ReceptionService")
ReceptionService service;
#Override
protected void init(VaadinRequest request) {
UI.getCurrent().setLocale(new Locale("nb","no"));
setSizeFull();
String message = service.welcome();
Label label = new Label("message: " + message);
setContent(new HorizontalLayout(label));
}
It is also still needed to register module dependency, so that the client class loader can see the service. I do it in the webapp pom.xml using the war-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Dependencies>deployment.template-service-1.0.0-SNAPSHOT.jar</Dependencies>
</manifestEntries>
</archive>
</configuration>
</plugin>
This way I am able to deploy my ejbs separately, and I can then deploy my war-file as a "thin" deployment. My real-world project has a bunch of ejbs and jpa-stuff which slows down the develops-compile-deploy cycle when I work on the gut-stuff, with this setup I can save quite some time when fiddling with the gui.
The EJB looks like this, no ejb-jar.xml.
#Stateless
public class ReceptionService {
public String welcome() {
return "Hello, Developer! No XML, No Configuration, and it works!!!";
}
}
The no-xml-part in the message would only be true if you added the module dependency to your manifest manually, and not using war-plugin :o)
Edit: to include dependencies in the ejb jar one can use one-jar plugin or similar.

It is possible to override properties in a persistence.xml that is located in a jar dependency

I have a java-ee web application that uses a persistence unit that is packaged as a jar dependency (Entity classes, EJB repositories, persistence.xml).
In order to get some acceptance tests running for the web application i need to override a property in the packaged persistence.xml. To be specific i need to disable the by default active eclipselink shared object cache by setting the following property.
<property name="eclipselink.cache.shared.default" value="false"/>
This is necessary because the acceptance tests are directly prepare/cleanup the database with dbunit. These modifications will put the eclipselink cache in a stale state (because the persistence unit is not involved in these modifications).
Is there a way in java-ee (or glassfish specific) to override properties in a persistence.xml that is located in a jar (starting from the web application war file, that is deployed when running my tests)?
There may be other ways, for example building the jar dependency specific for a test deployment, but this route seems complicated to me for only override one property in my persistence.xml.
You can pass a properties map to Persistence.createEntityManagerFactory(). To do this you must manage your persistence context yourself (will not be able to inject it).
Another option is to set the property as a Java system property (-D=), this will not override an existing property in the persistence.xml, but with work if the property is not in the persistence.xml.
Another option is to put a SessionCustomizer or a SessionTuner in your persistence.xml to allow your own code to modify the configuration at runtime.

EclipseLink, EntityManager with two persistence units needed

I have one jar library A (or project in eclipse), which has it's own persistence unit (META-INF/persistence.xml) and some entity classes, and another project (B) using this one. In project B there is also persistence unit and entity classes.
In project B I need to use both entity classes from project A and B. But if I set "A" as persistence unit name, EntityManager cannot create named query if this query is in entity from project B. If I set "B" as persistence unit name, it cannot create named queries from entities from project A. Error message is:
NamedQuery of name: MyEntityName.myQueryName not found.
Can persistence units somehow include other persistence units? Or is there any other way to solve this problem?
EclipseLink 2.3 introduced Composite Persistence Units, which allows you to create a persistence unit that essentially acts only as a container for two or more actual persistence units. You are then able to use this single composite persistence unit in your application as if you had only one persistence unit. This should meet your goals of keeping your persistence.xml files clean for easy synchronization of your model to database. Pretty cool stuff.
You can list your classes needed by A in one persistence unit, and classes needed you B in an other:
<persistence ...>
<persistence-unit name="projectA" ...>
....
<class>a.Class1</class>
<class>a.Class2</class>
<class>a.Class3</class>
</persistence-unit>
<persistence-unit name="projectB" ...>
...
<class>a.Class1</class>
<class>a.Class2</class>
<class>a.Class3</class>
<class>b.Class1</class>
<class>b.Class2</class>
<class>b.Class3</class>
</persistence-unit>
</persistence>
Alternatively, you can use the <jar-file> element, quoting from the JPA spec (6.2.1.6): "If specified, these JAR files will be searched for managed persistence classes, and any mapping metadata annotations found on them will be processed, or they will be mapped using the mapping annotation defaults defined by this specification. Such JAR files are specified relative to the root of the persistence unit (e.g., utils/myUtils.jar)."
<persistence ...>
<persistence-unit name="projectA" ...>
...
<jar-file>relative/path/to/your/library.jar</jar-file>
</persistence-unit>
</persistence>

JBoss 5 AS and EJB3 bean injection from servlets?

It was my understanding that JBossAS 5.x supported EJB3 bean injection in servlets with the #EJB3 annotation. I'm using the default configuration for JBossAS 5.0.1.GA and it's not working. I've added the mappedName argument to the #EJB annotation with the session beans JNDI name, and it just doesn't do anything. No apparent errors, the bean is just never injected.
The session beans are in the ejb-jar, the servlets in a war, everything is packaged in an ear. Manual JNDI lookups work just fine. Any ideas?
This may happen if your web.xml points to an older version of the spec. Ideally, it should be something like
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd">
This link may help a little too.
You should also check the jar file needed for EJB3 deployment in the classpath.JAr file is jboss-ejb3-ext-api.jar.