Hi,

thanks for your reply. I found your documentation pretty good. I came across the RuntimeUnenhancedClasses property but overlooked the UN of Unenhanced and thus didn't give it a try.

However the adjusted example (see attachment) still gives me:
  The type "...Person" has not been enhanced.
- the properties passed to Persistence.createEntityManagerFactory()
  now have the openjpa.RuntimeUnenhancedClasses=supported
  setting.
- on the MetaDataRepsoitory of the EntityManagerFactory, I
  call addMetaData( Person.class ).
what else am I missing?

Cheers,
Rüdiger

Pinaki Poddar wrote:
Hi,

The configuration property name is "openjpa.RuntimeUnenhancedClasses" and
possible values are "supported", "unsupported" and "warn". With "supported",
OpenJPA will be able to work with normal user-defined classes i.e. without
any byte-code enhancement.
MetaDataRepository#addMetaData() or
MetaDataRepository#addPersistenceAware() (no idea what the difference is)

PersistenceCapable refers to classes that are managed by JPA provider. To
manage them properly, JPA provider needs to intercept any read/write access
to fields of PersistenceCapable class. Different techniques (e.g. proxying,
subclassing, byte-code enhancement) can be used to intercept without
impacting user-defined classes. OpenJPA traditionally used build-time (i.e.
post-compile, pre-runtime) byte-code enhancement as the only mechanics for
interception. Later, more choices have been added that allows you to choose
when byte-code enhancement takes place [1] or even using other technique
such as subclassing rather than byte-code enhancement [2].

PersistenceAware refers to classes that *directly* access/mutate fields of
PersistenceCapable instances. This can happen when fields of
PersistenceCapable classes are declared at public or package level access.
OpenJPA requires PersistenceAware classes also to be enhanced.

I couldn't find further information on how to disable class enhancement.

This is not good news for our documentation effort :)


[1]
http://openjpa.apache.org/docs/latest/manual/manual.html#ref_guide_pc_enhance
[2]
http://openjpa.apache.org/docs/latest/manual/manual.html#ref_guide_pc_enhance_unenhanced_types



Rüdiger Herrmann wrote:
Hi,

using OpenJPA in a JavaSE (Eclipse RCP) environment, I would like to register JPA-annotated classes that will participate in the persistence mechanism at runtime.

Background:
Presistence-aware classes are contributed via Eclipse Extension Points. All these classes have JPA annotations.

Furthermore I don't want to use class enhancement as I don't have control over the VM startup parameters (like -javaagent) in which the application is running in. Though there seems to be an effort to make class enhancement optional ([1]), I couldn't find further information on how to disable class enhancement.

I played around with the attached code (persist one instance of class Person that has no further dependencies/references) but I couldn't get it to work.

The various attempts resulted either in
   Attempt to cast instance "...Person..." to
   PersistenceCapable failed.  Ensure that it
   has been enhanced.
or
   The type "class org.example.openjpatest.Person"
   has not been enhanced.
depending on wether I called MetaDataRepository#addMetaData() or MetaDataRepository#addPersistenceAware() (no idea what the difference is) and wether I called mernge() before persist().

If desired I can send the full (Eclipse) project with all required jars (HSQL, OpenJPA plus dependencies, JTA) that runs out-of-the-box.


Thanks in advance
Rüdiger

[1] https://issues.apache.org/jira/browse/OPENJPA-293

package org.example.openjpatest;

import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.persistence.EntityManagerFactoryImpl;


public class NoEnhancerExample {

  public static void main( String[] args ) {
    NoEnhancerExample example = new NoEnhancerExample();
    EntityManagerFactory factory = example.createEntityManagerFactory();
    EntityManager manager = factory.createEntityManager();
    Person person = new Person();
    person.setName( "first person" );
    manager.merge( person );
    manager.persist( person );
    factory.close();
  }

private EntityManagerFactory createEntityManagerFactory() { Map<String, String> properties = new HashMap<String, String>();
    properties.put( "openjpa.ConnectionUserName", "sa" );
    properties.put( "openjpa.ConnectionPassword", "" );
    properties.put( "openjpa.ConnectionURL",
"jdbc:hsqldb:mem:SqlModelStore_Test" );
    properties.put( "openjpa.ConnectionDriverName",
"org.hsqldb.jdbcDriver" );
properties.put( "openjpa.ConnectionFactoryProperties", "PrettyPrint=true, PrettyPrintLineLength=80" ); properties.put( "openjpa.Log", "DefaultLevel=WARN, Runtime=INFO, Tool=INFO,
SQL=TRACE" );
    EntityManagerFactory result
      = Persistence.createEntityManagerFactory( "model", properties );
    initOpenJpa( result );
    return result;
  }

  private void initOpenJpa( EntityManagerFactory factory ) {
    EntityManagerFactoryImpl factoryImpl
      = ( EntityManagerFactoryImpl )factory;
    MetaDataRepository metaDataRepository
      = factoryImpl.getConfiguration().getMetaDataRepositoryInstance();
//    metaDataRepository.addPersistenceAware( Person.class );
    metaDataRepository.addMetaData( Person.class );
  }
}

package org.example.openjpatest;

import java.util.UUID;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Person {
@Id
  private String id;
  private String name;

public Person() {
    id = UUID.randomUUID().toString();
  }
public String getId() {
    return id;
  }

  public void setName( String name ) {
    this.name = name;
  }

  public String getName() {
    return name;
  }
}



package org.example.openjpatest;

import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.persistence.EntityManagerFactoryImpl;


public class NoEnhancerExample {

  public static void main( String[] args ) {
    NoEnhancerExample example = new NoEnhancerExample();
    EntityManagerFactory factory = example.createEntityManagerFactory();
    EntityManager manager = factory.createEntityManager();
    Person person = new Person();
    person.setName( "first person" );
    manager.merge( person );
    manager.persist( person );
    factory.close();
  }

  private EntityManagerFactory createEntityManagerFactory() { 
    Map<String, String> properties = new HashMap<String, String>();
    properties.put( "openjpa.RuntimeUnenhancedClasses", "supported" );
    properties.put( "openjpa.ConnectionUserName", "sa" );
    properties.put( "openjpa.ConnectionPassword", "" );
    properties.put( "openjpa.ConnectionURL", 
"jdbc:hsqldb:mem:SqlModelStore_Test" );
    properties.put( "openjpa.ConnectionDriverName", "org.hsqldb.jdbcDriver" );
    properties.put( "openjpa.ConnectionFactoryProperties", 
                    "PrettyPrint=true, PrettyPrintLineLength=80" );
    properties.put( "openjpa.Log", 
                    "DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE" );
    EntityManagerFactory result
      = Persistence.createEntityManagerFactory( "model", properties );
    initOpenJpa( result );
    return result;
  }

  private void initOpenJpa( EntityManagerFactory factory ) {
    EntityManagerFactoryImpl factoryImpl
      = ( EntityManagerFactoryImpl )factory;
    MetaDataRepository metaDataRepository
      = factoryImpl.getConfiguration().getMetaDataRepositoryInstance();
//    metaDataRepository.addPersistenceAware( Person.class );
    metaDataRepository.addMetaData( Person.class );
  }
}
package org.example.openjpatest;

import java.util.UUID;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Person {
  
  @Id
  private String id;
  private String name;
  
  public Person() {
    id = UUID.randomUUID().toString();
  }
  
  public String getId() {
    return id;
  }
  
  public void setName( String name ) {
    this.name = name;
  }

  public String getName() {
    return name;
  }
}

Reply via email to