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

Reply via email to