...sorry, due to a wrong key combination, I've sent the previous message
while writing it!

I continue from point 4.
here is an excerpt of the test app with the relevant part of the code:

public class TestApp implements Runnable {

  private EntityManagerFactory entityManagerFactory;

  // [...omitting start, stop and implementation of invoking the
updateEntity at regular intervals...]

  public void setEntityManagerFactory(EntityManagerFactory
entityManagerFactory) {
    this.entityManagerFactory = entityManagerFactory;
  }

  private void createEntity() {
    TestEntity entity = new TestEntity(sessionId);
    EntityManager em = entityManagerFactory.createEntityManager();
    em.getTransaction().begin();
    em.persist(entity);
    em.getTransaction().commit();
    em.close();
  }

  private void removeEntity() {
    EntityManager em = entityManagerFactory.createEntityManager();
    em.getTransaction().begin();
    TestEntity entity = em.find(TestEntity.class, sessionId);
    em.remove(entity);
    em.getTransaction().commit();
    em.close();
  }

  private void updateEntity() {
    EntityManager em = entityManagerFactory.createEntityManager();
    em.getTransaction().begin();

    TestEntity entity = em.find(TestEntity.class, sessionId);
    if (entity.time != null) {
      entity.description = "Previously invoked at " +
dateFormat.format(entity.time);
      entity.value = entity.description.getBytes();
    }
    entity.time = new Date();
    entity.calls += 1;

    em.getTransaction().commit();
    em.close();
  }
}
In the test app I inject the entity manager factory which I create with
spring-orm, after starting the app, I just manually check the DB to see if
everything works as expected.

5. The beans.xml file:

<beans ...>
    <bean id="mysqlDataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url"
value="jdbc:mysql://localhost:3306/test_integration" />
        <property name="username" value="root" />
        <property name="password" value="" />
    </bean>

    <!-- <bean id="hsqlDataSource" -->
        <!--
class="org.springframework.jdbc.datasource.DriverManagerDataSource"> -->
        <!-- <property name="driverClassName" value="org.hsqldb.jdbcDriver"
/> -->
        <!-- <property name="url" value="jdbc:hsqldb:mem:test_integration"
/> -->
        <!-- <property name="username" value="sa" /> -->
        <!-- <property name="password" value="" /> -->
    <!-- </bean> -->

    <bean id="emf"

class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="mysqlDataSource" />
        <property name="persistenceUnitName" value="test-pu" />
        <property name="loadTimeWeaver">
            <bean class="net.cristcost.test.TestWeaver" />
        </property>
        <property name="jpaVendorAdapter">
            <bean

class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
                <property name="showSql" value="true" />
            </bean>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="eclipselink.ddl-generation">create-tables</prop>
                <prop
key="eclipselink.ddl-generation.output-mode">database</prop>
                <prop key="eclipselink.logging.level">INFO</prop>
            </props>
        </property>
    </bean>

    <bean id="testApp" class="net.cristcost.test.TestApp"
init-method="osgiInit"
destroy-method="osgiDestroy">
    <!-- Note: osgiInit invoke the createEntity() method and start the
scheduler for invoking the updateEntity() -->
        <property name="entityManagerFactory" ref="emf" />
    </bean>

</beans>

There is one caveat that I will get back on later, but this bundle,
deployed on ServiceMix successfully writes and reads from the database on
using JPA.


6. The caveat is: I've written by myself a simple LoadTimeWeaver (no
LoadTimeWeaver from spring-orm was working for me with the combination of
Spring 3.0.7-RELEASE and  Eclipselink 2.5.0.
In fact, the org.springframework.instrument.classloading.SimpleLoadTimeWeaver
that is usually found on examples was not working for me even in a simple
Java SE application!
With EclipseLink, I was getting weird exceptions the most notable was the
ClassCastException that was unable to cast TestEntity to TestEntity.

My net.cristcost.test.TestWeaver simply return its classloader. Here is the
code:

import org.springframework.instrument.classloading.LoadTimeWeaver;
import java.lang.instrument.ClassFileTransformer;

public class TestWeaver implements LoadTimeWeaver {

  @Override
  public void addTransformer(ClassFileTransformer transformer) {
    // I ignore the ClassFileTransformer
  }

  @Override
  public ClassLoader getInstrumentableClassLoader() {
    return this.getClass().getClassLoader();
  }

  @Override
  public ClassLoader getThrowawayClassLoader() {
    return this.getClass().getClassLoader();
  }
}

I did this to solve the ClassCastException while running in Java SE, I then
tried to put the bundle in ServiceMix, I was not expecting it to work but
it did!

I understand that this "weaver" is not good, especially for deployment in a
production environment, but the test work and I don't have enough
experience for understanding what "weavers" should do especially in an OSGi
environment.

Any comments on this approach, especially if there is some way to improve
the LoadTimeWeaver to be more respectful of the context (osgi) where I'm
going to deploy it?

Thank you all,
sorry for having broken the mail in two parts! :-P

Cristiano



2013/8/7 Cristiano Costantini <[email protected]>

> Hi All,
>
> it is days I am investigating how to use JPA with Eclipselink under
> ServiceMix using an approach that satisfy me. I prefer not to use
> karaf-enterprise (at least until I fully understand it) and so I avoided
> using the Servicemix's "jpa" feature, and I focused on spring-orm, that is
> a available as a feature too in the standard assembly. I also prefer it as
> my applications use spring and not blueprint for deployment.
>
> So, today I've achieved some significant result as my test application is
> working and successfully writing and reading from both an HSQLDB and Mysql
> from within a bundle running on ServiceMix 4.5.2 with Eclipselink 2.5.0.
>
> Even if it works, there are some weird aspect that I would like the have
> some feedback about, but I will explain fully my test application in the
> hope it may be helpful for someone else.
>
> (I'm writing a lot of code in the mail, I'm going to leave some days for
> holidays, when I'm back, if someone ask for it, I can try to clean and
> publish this test application as an example for others to work on)
>
>
> 1. As first step, I show the dependencies I installed on servicemix.
> I've created a feature with my bundles plus all the dependencies:
>
> <feature name="osgijpa-test" version="1.0">
>     <feature>spring-orm</feature>
>
>     <bundle>mvn:mysql/mysql-connector-java/5.1.26</bundle>
>     <bundle>mvn:org.hsqldb/hsqldb/2.2.9</bundle>
>
> <bundle>mvn:net.cristcost.test/springjdbc-mysql-fragment/1.0-SNAPSHOT</bundle>
>
>     <bundle>mvn:org.eclipse.persistence/javax.persistence/2.1.0</bundle>
>
> <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.antlr/2.5.0</bundle>
>
> <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.asm/2.5.0</bundle>
>
> <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.core/2.5.0</bundle>
>
> <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.jpa.jpql/2.5.0</bundle>
>
> <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.jpa/2.5.0</bundle>
>
>
>
> <bundle>mvn:net.cristcost.test/osgijpa-testapp-bundle/1.0-SNAPSHOT</bundle>
> </feature>
>
> The test app is the last bundle in the list. Some relevant things to note:
> a. spring-orm also install spring-jdbc
> b. for mysql, only recent driver are osgi ready - I was using version
> 5.1.6 which wasn't
> c. spring-jdbc does not support out of the box mysql (see
> http://planet.jboss.org/post/how_to_use_jdbc_driver_in_osgi_container),
> you need to create a fragment that extends it and I did by creating a
> bundle (springjdbc-mysql-fragment) which actually is all about configuring
> the maven-bundle-plugin in the pom.xml with the following two options:
> <Fragment-Host>org.springframework.jdbc</Fragment-Host>
> <Import-Package>com.mysql.jdbc</Import-Package>
>
> Open question:
> - why does spring-jdbc does not support out of the box mysql by importing
> its driver package as it does for so many other drivers?
>
>
> 2. The persistence unit I am using in servicemix:
> <persistence-unit name="test-pu" transaction-type="RESOURCE_LOCAL">
> <class>net.cristcost.test.TestEntity</class>
> </persistence-unit>
>
> all the rest of the configuration is passed by spring-orm in the spring's
> beans configuration file.
> The file is deployed within the META-INF folder of the
> osgijpa-testapp-bundle bundle.
>
> 3. The TestEntity class is a simple class used for test purposes:
> @Entity
> @Table(name = "\"test_entities\"")
> public class TestEntity {
>   public TestEntity() {}
>   public TestEntity(String id) {this.id = id; this.calls = 0; }
>
>   @Id
>   @Column(name = "\"id\"", unique = true, nullable = false)
>   public String id;
>
>   @Column(name = "\"description\"")
>   public String description;
>
>   @Column(name = "\"time\"")
>   @Temporal(TemporalType.TIMESTAMP)
>   public Date time;
>
>   @Column(name = "\"calls\"")
>   public int calls;
>
>   @Lob
>   @Column(name = "\"value\"", nullable = true)
>   public byte[] value;
> }
>
>
> 4. I wrote a test application that was possible to execute both in a
> bundle in servicemix and outside, in simple java console application.
> Omitting the code for bootstrap, here is the
>
>
> Regards,
> Cristiano
>

Reply via email to