This is an automated email from the ASF dual-hosted git repository. jgallimore pushed a commit to branch tomee-7.0.x in repository https://gitbox.apache.org/repos/asf/tomee.git
The following commit(s) were added to refs/heads/tomee-7.0.x by this push: new 02b9b4e Syncing CMP/JPA code up with master 02b9b4e is described below commit 02b9b4e201d9e69975649b7385a1b6a2b5ec73c4 Author: Jonathan Gallimore <j...@jrg.me.uk> AuthorDate: Wed Jul 24 11:01:46 2019 +0100 Syncing CMP/JPA code up with master --- .../tests/cmp/sample/CustomOrmXmlCastTest.java | 76 +++++++++++++++ .../tests/cmp/sample/CustomOrmXmlEarTest.java | 90 +++++++++++++++++ .../cmp/sample/CustomOrmXmlHibernateEarTest.java | 106 +++++++++++++++++++++ .../tests/cmp/sample/MoviesServlet2.java | 89 +++++++++++++++++ .../arquillian/tests/cmp/sample/application.xml | 12 +++ .../tests/cmp/sample/persistence-hibernate.xml | 32 +++++++ .../apache/openejb/config/CmpJpaConversion.java | 75 ++++++++------- 7 files changed, 448 insertions(+), 32 deletions(-) diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/CustomOrmXmlCastTest.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/CustomOrmXmlCastTest.java new file mode 100644 index 0000000..af88bd9 --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/CustomOrmXmlCastTest.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.arquillian.tests.cmp.sample; + +import org.apache.ziplock.IO; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.net.URL; + +/** + * @version $Rev$ $Date$ + */ +@RunWith(Arquillian.class) +public class CustomOrmXmlCastTest { + + @ArquillianResource + private URL url; + + @Deployment(testable = false) + public static WebArchive createDeployment() { + final WebArchive archive = ShrinkWrap.create(WebArchive.class, CustomOrmXmlCastTest.class.getSimpleName() + ".war") + .addClasses(ActorBean.class, ActorDetails.class, LocalActor.class, LocalActorHome.class, + LocalMovie.class, LocalMovieHome.class, MovieBean.class, MovieDetails.class, + MoviesBusiness.class, MoviesBusinessBean.class, MoviesBusinessHome.class, MoviesServlet.class, + MoviesServlet2.class) + .addAsResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/custom-orm.xml"), "META-INF/custom-orm.xml") + .addAsResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/persistence.xml"), "META-INF/persistence.xml") + .addAsWebInfResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/openejb-jar.xml"), "openejb-jar.xml") + .addAsWebInfResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/ejb-jar.xml"), "ejb-jar.xml") + .addAsWebInfResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/web.xml"), "web.xml"); + + System.out.println(archive.toString(true)); + return archive; + } + + @Test + @RunAsClient + public void checkCmpJpaEntityORMMappings() throws Exception { + final String output = IO.slurp(new URL(url.toExternalForm())); + System.out.println(output); + + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR, COLUMN_NAME: ACTORID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR, COLUMN_NAME: ACTOR_NAME, DATA_TYPE: CHARACTER VARYING, CHARACTER_MAXIMUM_LENGTH: 250")); + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR_MOVIE, COLUMN_NAME: ACTORS_ACTORID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR_MOVIE, COLUMN_NAME: MOVIES_MOVIEID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: MOVIE, COLUMN_NAME: MOVIEID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: MOVIE, COLUMN_NAME: GENRE, DATA_TYPE: CHARACTER VARYING, CHARACTER_MAXIMUM_LENGTH: 255")); + Assert.assertTrue(output.contains("TABLE_NAME: MOVIE, COLUMN_NAME: MOVIE_NAME, DATA_TYPE: CHARACTER VARYING, CHARACTER_MAXIMUM_LENGTH: 250")); + + final String[] split = output.split("\r?\n"); + Assert.assertEquals(7, split.length); + } +} diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/CustomOrmXmlEarTest.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/CustomOrmXmlEarTest.java new file mode 100644 index 0000000..da042bc --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/CustomOrmXmlEarTest.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.arquillian.tests.cmp.sample; + +import org.apache.ziplock.IO; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset; +import org.jboss.shrinkwrap.api.spec.EnterpriseArchive; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.net.URL; + +/** + * @version $Rev$ $Date$ + */ +@RunWith(Arquillian.class) +public class CustomOrmXmlEarTest { + + @ArquillianResource + private URL url; + + @Deployment(testable = false) + public static EnterpriseArchive createDeployment() { + + final JavaArchive clientJar = ShrinkWrap.create(JavaArchive.class, "client.jar") + .addClasses(ActorDetails.class, LocalActor.class, LocalActorHome.class, + LocalMovie.class, LocalMovieHome.class, MovieDetails.class, + MoviesBusiness.class, MoviesBusinessHome.class); + + final JavaArchive ejbJar = ShrinkWrap.create(JavaArchive.class, "ejb-jar.jar") + .addClasses(ActorBean.class, MovieBean.class, MovieDetails.class, MoviesBusinessBean.class) + .addAsResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/custom-orm.xml"), "META-INF/custom-orm.xml") + .addAsResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/persistence.xml"), "META-INF/persistence.xml") + .addAsResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/openejb-jar.xml"), "META-INF/openejb-jar.xml") + .addAsResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/ejb-jar.xml"), "META-INF/ejb-jar.xml"); + + final WebArchive testWar = ShrinkWrap.create(WebArchive.class, "test.war") + .addClass(MoviesServlet.class) + .addAsWebInfResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/web.xml"), "web.xml"); + + final EnterpriseArchive archive = ShrinkWrap.create(EnterpriseArchive.class, "test.ear") + .addAsLibrary(clientJar) + .addAsModule(ejbJar) + .addAsModule(testWar); + + System.out.println(archive.toString(true)); + return archive; + } + + + @Test + @RunAsClient + public void checkCmpJpaEntityORMMappings() throws Exception { + final String output = IO.slurp(new URL(url.toExternalForm() + "/test/test/")); + System.out.println(output); + + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR, COLUMN_NAME: ACTORID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR, COLUMN_NAME: ACTOR_NAME, DATA_TYPE: CHARACTER VARYING, CHARACTER_MAXIMUM_LENGTH: 250")); + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR_MOVIE, COLUMN_NAME: ACTORS_ACTORID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR_MOVIE, COLUMN_NAME: MOVIES_MOVIEID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: MOVIE, COLUMN_NAME: MOVIEID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: MOVIE, COLUMN_NAME: GENRE, DATA_TYPE: CHARACTER VARYING, CHARACTER_MAXIMUM_LENGTH: 255")); + Assert.assertTrue(output.contains("TABLE_NAME: MOVIE, COLUMN_NAME: MOVIE_NAME, DATA_TYPE: CHARACTER VARYING, CHARACTER_MAXIMUM_LENGTH: 250")); + + final String[] split = output.split("\r?\n"); + Assert.assertEquals(7, split.length); + } +} \ No newline at end of file diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/CustomOrmXmlHibernateEarTest.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/CustomOrmXmlHibernateEarTest.java new file mode 100644 index 0000000..c6a4b2b --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/CustomOrmXmlHibernateEarTest.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.arquillian.tests.cmp.sample; + +import org.apache.ziplock.IO; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset; +import org.jboss.shrinkwrap.api.spec.EnterpriseArchive; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.resolver.api.maven.Maven; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.net.URL; + +/** + * @version $Rev$ $Date$ + */ +@RunWith(Arquillian.class) +public class CustomOrmXmlHibernateEarTest { + + @ArquillianResource + private URL url; + + @Deployment(testable = false) + public static EnterpriseArchive createDeployment() { + + final JavaArchive clientJar = ShrinkWrap.create(JavaArchive.class, "client.jar") + .addClasses(ActorDetails.class, LocalActor.class, LocalActorHome.class, + LocalMovie.class, LocalMovieHome.class, MovieDetails.class, + MoviesBusiness.class, MoviesBusinessHome.class); + + final JavaArchive ejbJar = ShrinkWrap.create(JavaArchive.class, "ejb-jar.jar") + .addClasses(ActorBean.class, MovieBean.class, MovieDetails.class, MoviesBusinessBean.class) + .addAsResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/custom-orm.xml"), "META-INF/custom-orm.xml") + .addAsResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/persistence-hibernate.xml"), "META-INF/persistence.xml") + .addAsResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/openejb-jar.xml"), "META-INF/openejb-jar.xml") + .addAsResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/ejb-jar.xml"), "META-INF/ejb-jar.xml"); + + final WebArchive testWar = ShrinkWrap.create(WebArchive.class, "test.war") + .addClass(MoviesServlet.class) + .addAsWebInfResource(new ClassLoaderAsset("org/apache/openejb/arquillian/tests/cmp/sample/web.xml"), "web.xml"); + + final File[] hibernateDependencies = Maven.resolver().resolve( + "org.hibernate:hibernate-entitymanager:4.3.9.Final", + "org.hibernate:hibernate-core:4.3.9.Final", + "org.hibernate.common:hibernate-commons-annotations:4.0.5.Final", + "antlr:antlr:2.7.7", + "org.jboss:jandex:1.1.0.Final", + "org.jboss.logging:jboss-logging:3.1.3.GA", + "org.jboss.logging:jboss-logging-annotations:1.2.0.Beta1", + "dom4j:dom4j:1.6.1", + "org.javassist:javassist:3.18.1-GA", + "mysql:mysql-connector-java:5.1.13" + ).withoutTransitivity().asFile(); + + final EnterpriseArchive archive = ShrinkWrap.create(EnterpriseArchive.class, "test.ear") + .addAsLibrary(clientJar) + .addAsLibraries(hibernateDependencies) + .addAsModule(ejbJar) + .addAsModule(testWar); + + System.out.println(archive.toString(true)); + return archive; + } + + + @Test + @RunAsClient + public void checkCmpJpaEntityORMMappings() throws Exception { + final String output = IO.slurp(new URL(url.toExternalForm() + "/test/test/")); + System.out.println(output); + + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR, COLUMN_NAME: ACTORID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR, COLUMN_NAME: ACTOR_NAME, DATA_TYPE: CHARACTER VARYING, CHARACTER_MAXIMUM_LENGTH: 250")); + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR_MOVIE, COLUMN_NAME: ACTORS_ACTORID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: ACTOR_MOVIE, COLUMN_NAME: MOVIES_MOVIEID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: MOVIE, COLUMN_NAME: MOVIEID, DATA_TYPE: INTEGER, CHARACTER_MAXIMUM_LENGTH: null")); + Assert.assertTrue(output.contains("TABLE_NAME: MOVIE, COLUMN_NAME: GENRE, DATA_TYPE: CHARACTER VARYING, CHARACTER_MAXIMUM_LENGTH: 255")); + Assert.assertTrue(output.contains("TABLE_NAME: MOVIE, COLUMN_NAME: MOVIE_NAME, DATA_TYPE: CHARACTER VARYING, CHARACTER_MAXIMUM_LENGTH: 250")); + + final String[] split = output.split("\r?\n"); + Assert.assertEquals(7, split.length); + } +} \ No newline at end of file diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/MoviesServlet2.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/MoviesServlet2.java new file mode 100644 index 0000000..007ba0e --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/cmp/sample/MoviesServlet2.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.openejb.arquillian.tests.cmp.sample; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.sql.DataSource; +import java.io.IOException; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; + + +public class MoviesServlet2 extends HttpServlet { + + @Override + protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { + try { + + final PrintWriter pw = resp.getWriter(); + + final Context initial = new InitialContext(); + + final MoviesBusinessHome home = (MoviesBusinessHome) initial.lookup("java:comp/env/ejb/MoviesBusiness"); + + final MoviesBusiness moviesBusiness = home.create(); + moviesBusiness.doLogic(); + + final DataSource ds = (DataSource) initial.lookup("java:comp/env/db/DataSource"); + try (final Connection connection = ds.getConnection(); + final PreparedStatement ps = connection.prepareStatement( + "select TABLE_NAME, COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH " + + "from INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA = 'PUBLIC' and TABLE_NAME in ('ACTOR', 'MOVIE', 'ACTOR_MOVIE')"); + + final ResultSet rs = ps.executeQuery()) { + + final ResultSetMetaData metaData = rs.getMetaData(); + final int columnCount = metaData.getColumnCount(); + + final String[] columnNames = new String[columnCount]; + + for (int c = 0; c < columnCount; c++) { + columnNames[c] = metaData.getColumnName(c + 1); + } + + while (rs.next()) { + final StringBuilder sb = new StringBuilder(); + + for (int c = 0; c < columnCount; c++) { + if (c > 0) { + sb.append(", "); + } + + sb.append(columnNames[c]).append(": ").append(rs.getString(c + 1)); + } + + pw.println(sb.toString()); + } + } + + pw.flush(); + + } catch (final Exception ex) { + throw new ServletException(ex); + } + } + +} diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/resources/org/apache/openejb/arquillian/tests/cmp/sample/application.xml b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/resources/org/apache/openejb/arquillian/tests/cmp/sample/application.xml new file mode 100644 index 0000000..fcfcccb --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/resources/org/apache/openejb/arquillian/tests/cmp/sample/application.xml @@ -0,0 +1,12 @@ +<application> + <display-name>ear</display-name> + <module> + <ejb>EnterpriseArchive.jar</ejb> + </module> + <module> + <web> + <web-uri>EnterpriseArchive.war</web-uri> + <context-root>/test</context-root> + </web> + </module> +</application> \ No newline at end of file diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/resources/org/apache/openejb/arquillian/tests/cmp/sample/persistence-hibernate.xml b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/resources/org/apache/openejb/arquillian/tests/cmp/sample/persistence-hibernate.xml new file mode 100644 index 0000000..6799035 --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/resources/org/apache/openejb/arquillian/tests/cmp/sample/persistence-hibernate.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> + <persistence-unit name="cmp" transaction-type="JTA"> + <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> + <jta-data-source>My DataSource</jta-data-source> + <non-jta-data-source>My Unmanaged DataSource</non-jta-data-source> + <mapping-file>META-INF/custom-orm.xml</mapping-file> + <class>openejb.org.apache.openejb.arquillian.tests.cmp.sample.Movie</class> + <class>openejb.org.apache.openejb.arquillian.tests.cmp.sample.Actor</class> + <properties> + <property name="hibernate.hbm2ddl.auto" value="update"/> + <property name="hibernate.show_sql" value="true" /> + </properties> + </persistence-unit> +</persistence> \ No newline at end of file diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/CmpJpaConversion.java b/container/openejb-core/src/main/java/org/apache/openejb/config/CmpJpaConversion.java index 665f8f6..71ea091 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/CmpJpaConversion.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/CmpJpaConversion.java @@ -64,6 +64,7 @@ import org.apache.openejb.loader.SystemInstance; import org.apache.openejb.util.LogCategory; import org.apache.openejb.util.Logger; import org.apache.openejb.util.Strings; +import org.apache.xbean.finder.ResourceFinder; import javax.ejb.EJBLocalObject; import java.lang.reflect.Field; @@ -76,14 +77,16 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; -public class CmpJpaConversion implements DynamicDeployer { +class CmpJpaConversion implements DynamicDeployer { - private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, CmpJpaConversion.class); + private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, CmpJpaConversion.class); private static final String CMP_PERSISTENCE_UNIT_NAME = "cmp"; @@ -101,30 +104,21 @@ public class CmpJpaConversion implements DynamicDeployer { "pcDetachedState", "serialVersionUID" ))); + public static final String GENERATED_ORM_XML = "META-INF/openejb-cmp-generated-orm.xml"; - public static EntityMappings readEntityMappings(final String location) { - - // first try the classpath - EntityMappings entitymappings = null; + private static EntityMappings readEntityMappings(final String location, final AppModule appModule) { try { - final URL cpUrl = Thread.currentThread().getContextClassLoader().getResource(location); - entitymappings = (EntityMappings) JaxbJavaee.unmarshal(EntityMappings.class, IO.read(cpUrl)); - } catch (Exception e) { - // ignore - } - - if (entitymappings == null) { - // then try reading as a URL - try { - final URL url = new URL(location); - entitymappings = (EntityMappings) JaxbJavaee.unmarshal(EntityMappings.class, IO.read(url)); - } catch (Exception e) { - logger.error("Unable to read entity mappings from " + location, e); + final URL url = new ResourceFinder("", appModule.getClassLoader()).getResource(location); + if (Objects.isNull(url)) { + return null; } + return (EntityMappings) JaxbJavaee.unmarshal(EntityMappings.class, IO.read(url)); + } catch (Exception exp) { + LOGGER.error("Unable to read entity mappings from " + location, exp); + return null; } - return entitymappings; } public AppModule deploy(final AppModule appModule) throws OpenEJBException { @@ -141,7 +135,6 @@ public class CmpJpaConversion implements DynamicDeployer { appModule.setCmpMappings(cmpMappings); } - // todo scan existing persistence module for all entity mappings and don't generate mappings for them final Set<String> definedMappedClasses = new HashSet<String>(); @@ -150,7 +143,7 @@ public class CmpJpaConversion implements DynamicDeployer { if (cmpPersistenceUnit != null) { if (cmpPersistenceUnit.getMappingFile() != null && cmpPersistenceUnit.getMappingFile().size() > 0) { for (final String mappingFile : cmpPersistenceUnit.getMappingFile()) { - final EntityMappings entityMappings = readEntityMappings(mappingFile); + final EntityMappings entityMappings = readEntityMappings(mappingFile, appModule); if (entityMappings != null) { definedMappedClasses.addAll(entityMappings.getEntityMap().keySet()); } @@ -158,12 +151,12 @@ public class CmpJpaConversion implements DynamicDeployer { } } - // we process this one jar-file at a time...each contributing to the - // app mapping data + // we process this one jar-file at a time...each contributing to the + // app mapping data for (final EjbModule ejbModule : appModule.getEjbModules()) { final EjbJar ejbJar = ejbModule.getEjbJar(); - // scan for CMP entity beans and merge the data into the collective set + // scan for CMP entity beans and merge the data into the collective set for (final EnterpriseBean enterpriseBean : ejbJar.getEnterpriseBeans()) { if (isCmpEntity(enterpriseBean)) { processEntityBean(ejbModule, definedMappedClasses, cmpMappings, (EntityBean) enterpriseBean); @@ -171,7 +164,7 @@ public class CmpJpaConversion implements DynamicDeployer { } // if there are relationships defined in this jar, get a list of the defined - // entities and process the relationship maps. + // entities and process the relationship maps. final Relationships relationships = ejbJar.getRelationships(); if (relationships != null) { @@ -189,18 +182,34 @@ public class CmpJpaConversion implements DynamicDeployer { // so there can be no misunderstandings. final EntityMappings userMappings = getUserEntityMappings(ejbModule); for (final Entity mapping : userMappings.getEntity()) { - logger.warning("openejb-cmp-orm.xml mapping ignored: module=" + ejbModule.getModuleId() + ": <entity class=\"" + mapping.getClazz() + "\">"); + LOGGER.warning("openejb-cmp-orm.xml mapping ignored: module=" + ejbModule.getModuleId() + ": <entity class=\"" + mapping.getClazz() + "\">"); } for (final MappedSuperclass mapping : userMappings.getMappedSuperclass()) { - logger.warning("openejb-cmp-orm.xml mapping ignored: module=" + ejbModule.getModuleId() + ": <mapped-superclass class=\"" + mapping.getClazz() + "\">"); + LOGGER.warning("openejb-cmp-orm.xml mapping ignored: module=" + ejbModule.getModuleId() + ": <mapped-superclass class=\"" + mapping.getClazz() + "\">"); } } if (!cmpMappings.getEntity().isEmpty()) { final PersistenceUnit persistenceUnit = getCmpPersistenceUnit(appModule); - persistenceUnit.getMappingFile().add("META-INF/openejb-cmp-generated-orm.xml"); + final boolean generatedOrmXmlProvided = appModule.getClassLoader().getResource(GENERATED_ORM_XML) != null; + if (! persistenceUnit.getMappingFile().contains(GENERATED_ORM_XML)) { + // explicit check for openejb-cmp-generated-orm, as this is generated and added to <mapping-file> + if (generatedOrmXmlProvided) { + LOGGER.warning("App module " + appModule.getModuleId() + " provides " + GENERATED_ORM_XML + ", but does not " + + "specify it using <mapping-file> in persistence.xml for the CMP persistence unit, and it may conflict " + + "with the generated mapping file. Consider renaming the file and explicitly referencing it in persistence.xml"); + } + persistenceUnit.getMappingFile().add(GENERATED_ORM_XML); + } else { + if (generatedOrmXmlProvided) { + LOGGER.warning("App module " + appModule.getModuleId() + " provides " + GENERATED_ORM_XML + " and additionally " + + cmpMappings.getEntity().size() + "mappings have been generated. Consider renaming the " + GENERATED_ORM_XML + " in " + + "your deployment archive to avoid any conflicts."); + } + } + for (final Entity entity : cmpMappings.getEntity()) { if (!persistenceUnit.getClazz().contains(entity.getClazz())) { persistenceUnit.getClazz().add(entity.getClazz()); @@ -266,10 +275,12 @@ public class CmpJpaConversion implements DynamicDeployer { private String getPersistenceModuleId(final AppModule appModule) { if (appModule.getModuleId() != null) { - return appModule.getJarLocation() == null ? appModule.getModuleId() : appModule.getJarLocation(); + return Optional.ofNullable(appModule.getModuleUri().toString()).orElse(appModule.getModuleId()); } for (final EjbModule ejbModule : appModule.getEjbModules()) { - return appModule.getJarLocation() == null ? appModule.getModuleId() : appModule.getJarLocation(); + if (ejbModule.getModuleId() != null) { + return Optional.ofNullable(ejbModule.getModuleUri().toString()).orElse(ejbModule.getModuleId()); + } } throw new IllegalStateException("Comp must be in an ejb module, this one has none: " + appModule); } @@ -1012,7 +1023,7 @@ public class CmpJpaConversion implements DynamicDeployer { * levels of the class hierarchy. We want to define * the idClass as the most derived class (i.e., the one * that will contain ALL of the defined fields). - * <p/> + * * In practice, most ejbs will define all of the * primary key fields at the same subclass level, so * this should return quickly.