After debugging rather deeply, I discovered that it's a servlet container classloading issue. We are using Jetty 6.x, and when OpenJPA attempts to synchronize mappings, the Jetty classloader returns null when OpenJPA tries to load /WEB-INF/lib/case-model-1.1.0-SNAPSHOT.jar as a resource. If I copy the jar file to WEB-INF/classes, OpenJPA gets it from Jetty's classloader as a resource, scans it properly for entities, and everything is hunky dorey.
It seems to me that this is a bug in the servlet container. Since each jar in WEB-INF/lib is technically on the classpath, Jetty's classloader should allow OpenJPA to load it as a resource. I'll enter an issue in Jetty. I haven't check Tomcat yet -- I will and update the list with the results. The bug has nothing whatsoever do to with Spring. -matthew On Fri, Apr 30, 2010 at 3:52 PM, Patrick Linskey <[email protected]> wrote: > Hi, > > I think this is really more of a Spring question than an OpenJPA question -- > Spring is (presumably) using the JPA-provided bootstrapping API calls, which > don't allow for non-standard persistence.xml file locations. > > Once you get your persistence.xml file loaded properly, you'll have a lot > more flexibility in terms of telling OpenJPA where to load resources from etc. > > Depending on how the Spring PU creation code is implemented, you might be > able to have some success with your current approach by *not* specifying a > persistence.xml resource location, and instead providing one in the > appropriate OpenJPA property (I'm not sure what that'd be off the top of my > head). > > However.... what about putting all your persistence.xml files into the > standard resource location, and instead using different persistence unit > names for each store? You could do this by putting a number of directories > (or jars) into the classpath, and set up each to have a persistence.xml file. > Then, each one of those could point to a differently-named orm.xml file > stored in the same dir / jar. > > -Patrick > > On Apr 28, 2010, at 3:48 PM, Matthew Adams wrote: > >> Hi all, >> >> OpenJPA 1.2.2 is not generating my schema at compile time in a >> Spring-based MVC webapp, and I can't figure out why. See below for >> details. Help is appreciated. >> >> I am compiling, enhancing and jarring my entities in a jar called >> case-model-1.1.0-SNAPSHOT.jar, that does NOT contain a >> META-INF/persistence.xml or a META-INF/orm.xml, because they need to >> be determined at run time. Additionally, some of the entities have >> annotation-based mapping information defaults, like @Column which I'd >> like to have honored unless overridden by xml-based mapping metadata. >> >> Higher up in the dependency chain and in a separate project, I have a >> Spring web app that uses a service that depends on my entities, where >> I need to configure a custom persistence.xml and orm.xml that needs to >> be used along with the entities and their (possibly overridden) >> annotation-based mappings in the web app environment. >> >> I have put my Spring configuration files in WEB-INF/spring for all of >> the application, and the Spring configuration is configured with the >> help of a properties file located in a directory, call it >> "/configuration", that is made available to the web application but is >> not part of the web application itself. The diretory /configuration >> contains a directory called "linx2", wherein are located all of my >> configuration files. A properties file, called >> "linx2/linx2.properties", allows a user to indicate the database type >> in use via the "linx2.db.type" property, for example: >> >> linx2.db.type=hsqldb-memory >> linx2.db.url=jdbc:hsqldb:mem:linx2 >> linx2.db.driver=org.hsqldb.jdbcDriver >> linx2.db.user=sa >> linx2.db.password= >> ... >> >> That property is used in my Spring config to determine which >> persistence.xml and openjpa properties file to use: >> >> <bean id="entityManagerFactory" >> >> class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> >> <property name="persistenceUnitName" value="case-model" /> >> <property name="persistenceXmlLocation" >> >> value="classpath:/linx2/${linx2.db.type}-case-model-persistence.xml" /> >> <property name="jpaProperties"> >> <util:properties >> >> location="classpath:/linx2/${linx2.db.type}-openjpa.properties" /> >> </property> >> <property name="jpaVendorAdapter"> >> <bean >> class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter"> >> <property name="showSql" value="false" /> >> <property name="generateDdl" value="false" /> >> </bean> >> </property> >> <property name="dataSource" ref="dataSource" /> >> </bean> >> >> For good measure, here's my dataSource bean: >> >> <bean class="org.apache.commons.dbcp.BasicDataSource" >> name="dataSource"> >> <property name="driverClassName" value="${linx2.db.driver}" /> >> <property name="url" value="${linx2.db.url}" /> >> <property name="username" value="${linx2.db.user}" /> >> <property name="password" value="${linx2.db.password}" /> >> </bean> >> >> Because linx2.db.type is "hsqldb-memory", the persistence.xml file >> should be "linx2/hsqldb-memory-case-model-persistence.xml" and the >> openjpa properties file used should be >> "linx2/hsqldb-memory-openjpa.properties", both located in the >> directory "/configuration", which is on the classpath available to the >> webapp. Note that hsqldb-memory-case-model-persistence.xml is not in >> /configuration/linx2/META-INF -- it's directly in >> /configuration/linx2/. >> >> The contents of linx2/hsqldb-memory-openjpa.properties follow. Note >> the use of classpath scanning for the jar, >> case-model-1.1.0-SNAPSHOT.jar, containing the entities. >> >> openjpa.AutoDetach=commit >> openjpa.DetachState=fgs >> openjpa.QueryCache=false >> openjpa.jdbc.SubclassFetchMode=none >> openjpa.jdbc.EagerFetchMode=none >> openjpa.MetaDataFactory=jpa(ClasspathScan=case-model-1.1.0-SNAPSHOT.jar) >> openjpa.jdbc.SynchronizeMappings=buildSchema(ForeignKeys=false,Indexes=false) >> openjpa.Log=DefaultLevel=TRACE >> >> The contents of linx2/hsqldb-memory-case-model-persistence.xml follow. >> Note the use of the custom mapping file >> linx2/hsqldb-memory-case-model-orm.xml, which is located next to >> linx2/hsqldb-memory-case-model-persistence.xml in /configuration. >> >> <persistence xmlns="http://java.sun.com/xml/ns/persistence" >> version="1.0"> >> <persistence-unit name="case-model"> >> <provider> >> org.apache.openjpa.persistence.PersistenceProviderImpl >> </provider> >> <mapping-file>hsqldb-memory-case-model-orm.xml</mapping-file> >> </persistence-unit> >> </persistence> >> >> When I run the application and attempt to persist entities, I get the >> following error: >> >> <openjpa-1.2.2-r422266:898935 nonfatal general error> >> org.apache.openjpa.persistence.PersistenceException: Table not found >> in statement ... >> >> which tells me that the schema is not getting generated. I've >> confirmed this in the log -- no create table statements are being >> executed. >> >> In the log, I see that Spring is reporting something suspicious that I >> think might be related to the problem: >> >> 15:00:20.176 [main] INFO >> org.springframework.beans.factory.config.PropertiesFactoryBean - >> Loading properties file from class path resource >> [linx2/hsqldb-memory-openjpa.properties] >> 15:00:20.236 [main] INFO >> org.springframework.orm.jpa.persistenceunit.PersistenceUnitReader - >> hsqldb-memory-case-model-persistence.xml should be located inside >> META-INF directory; cannot determine persistence unit root URL for >> class path resource [linx2/hsqldb-memory-case-model-persistence.xml] >> 15:00:20.237 [main] INFO >> org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean - >> Building JPA container EntityManagerFactory for persistence unit >> 'case-model' >> >> So while Spring complains about not being able to determine the PU >> root URL, it builds the JPA container EMF for PU "case-model". >> >> Immediately thereafter, OpenJPA says it's looking for >> META-INF/orm.xml, even though my mapping file is >> linx2/hsqldb-memory-case-model-orm.xml: >> >> 3 model TRACE [main] openjpa.Runtime - Setting the following >> properties from "?" into configuration: {openjpa.DetachState=fgs, >> openjpa.connectionfactory=org.apache.commons.dbcp.basicdatasou...@173a0067, >> openjpa.jdbc.SynchronizeMappings=buildSchema(ForeignKeys=false,Indexes=false), >> javax.persistence.provider=org.apache.openjpa.persistence.PersistenceProviderImpl, >> openjpa.MetaDataFactory=jpa(ClasspathScan=case-model-1.1.0-SNAPSHOT.jar), >> openjpa.AutoDetach=commit, openjpa.jdbc.EagerFetchMode=none, >> openjpa.classresolver=org.apache.openjpa.persistence.persistenceunitinfoimpl$classresolveri...@2da896a4, >> openjpa.jdbc.SubclassFetchMode=none, openjpa.Log=DefaultLevel=TRACE, >> openjpa.QueryCache=false, openjpa.Id=case-model} >> 7 model TRACE [main] openjpa.Runtime - No cache marshaller found >> for id org.apache.openjpa.conf.MetaDataCacheMaintenance. >> 47 model TRACE [main] openjpa.MetaData - Scanning resource >> "META-INF/orm.xml" for persistent types. >> >> OpenJPA then seems to startup ok, correctly identifying the database >> and emitting the usual warning about registering a ClassTransformer, >> but with no mention of hsqldb-memory-case-model-persistence.xml or >> hsqldb-memory-case-model-orm.xml. >> >> Later, OpenJPA appears to be finding my entities ok and building >> metadata from them: >> >> 11710 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] >> openjpa.jdbc.JDBC - Initial connection autoCommit: true, holdability: >> 1, TransactionIsolation: 2 >> 11713 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] >> openjpa.jdbc.JDBC - <t 922745441, conn 0> [0 ms] close >> 11737 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] >> openjpa.jdbc.JDBC - DataSource connection setAutoCommit to "true" >> 11738 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] >> openjpa.jdbc.JDBC - <t 922745441, conn 0> [0 ms] close >> 11760 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] openjpa.MetaData >> - Scanning resource "META-INF/orm.xml" for persistent types. >> 11761 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] openjpa.MetaData >> - parsePersistentTypeNames() found []. >> 11761 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] openjpa.MetaData >> - Found 0 classes with metadata in 1 milliseconds. >> 11856 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] openjpa.MetaData >> - Processing registered persistence-capable class "class >> org.piercecountywa.linx.casemanagement.model.SpecialIdentificationProcedure". >> ... >> >> At the end of the transaction, I see the following in the log. Note >> the unexpected message about parsing class java.lang.String: >> >> ... >> 17096 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] openjpa.MetaData >> - Resolving field >> "org.piercecountywa.linx.casemanagement.model.vic...@907194328.incident". >> 17126 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] openjpa.MetaData >> - Parsing class "java.lang.String". >> 17133 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] openjpa.Query - >> Executing query: select d from SuperiorCourtDivision d where >> d.ajc$interField$org_piercecountywa_linx_casemanagement_model_aspects_NamedMixin$org_piercecountywa_linx_casemanagement_model_aspects_NamedMixin$IntroducedNamed$name >> = 'Criminal Division 1' >> 17173 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] >> openjpa.jdbc.JDBC - <t 922745441, conn 535160945> [0 ms] rollback >> 17174 case-model TRACE >> [casews-refid-6e511aa0-062a-4564-80a0-8c8c9c969b61-0] >> openjpa.jdbc.JDBC - <t 922745441, conn 0> [0 ms] close >> >> I also noticed that OpenJPA seems to be ignoring the mapping >> information on fields in entities in case-model-1.1.0-SNAPSHOT.jar. >> >> Can anyone help me here please? >> >> Thanks, >> Matthew >> -- >> mailto:[email protected] >> skype:matthewadams12 >> yahoo:matthewadams >> aol:matthewadams12 >> google-talk:[email protected] >> msn:[email protected] >> http://matthewadams.me >> http://www.linkedin.com/in/matthewadams > > -- > Patrick Linskey > 202 669 5907 > > -- mailto:[email protected] skype:matthewadams12 yahoo:matthewadams aol:matthewadams12 google-talk:[email protected] msn:[email protected] http://matthewadams.me http://www.linkedin.com/in/matthewadams
