Accueil > JPA, JPA/EclipseLink, Spring, Spring Data, Spring Data JPA, Spring DM, Spring ORM > Eclipse RCP/RAP with Spring DM, Spring Data JPA and Remoting [step6]

Eclipse RCP/RAP with Spring DM, Spring Data JPA and Remoting [step6]


In [step5] we have prepared the Target Platform with:

The API Dao fr.opensagres.dao.UserDao extends the Spring Data org.springframework.data.repository.PagingAndSortingRepository interface which is the first step to use Spring Data JPA.

In this article we will create several bundles/fragment to retrieves User list from a Database Derby with EclipseLink JPA. The JPA Dao implementation will be done with Spring Data JPA, on other words, you will do nothing (no need to code a JPAUserDao class). We will create 2 bundles and 1 fragment :

Download

You can download eclipsespring_step6.zip which contains the following explained projects :

  • fr.opensagres.domain : OSGi bundle domain which hosts fr.opensagres.domain.User class.
  • fr.opensagres.dao : OSGi bundle Dao API which hosts fr.opensagres.dao.UserDao interface.
  • fr.opensagres.dao.mock : OSGi bundle Dao Mock Implementation (Dao implemented with Java Map) which hosts a Spring file which declares the implementation of UserDao in a Spring bean and publish it the OSGi services registry with Spring DM <osgi:service.
  • fr.opensagres.dao.jpa the bundle implementation of UserDao with JPA by using Spring Data JPA to avoid coding the JPAUserDao class.
  • fr.opensagres.dao.jpa.eclipselink the fragment which configures the JPA fr.opensagres.dao.jpa to use EclipseLink and Deby as dialect.
  • fr.opensagres.data.datasource the bundle which publishes the Derby Datasource used by the fr.opensagres.dao.jpa.
  • fr.opensagres.services : OSGi bundle Services API which hosts fr.opensagres.services.UserService interface.
  • fr.opensagres.services.impl : OSGi bundle Services Implementation which hosts a Spring file which declares the implementation of UserService in a Spring bean and publish it the OSGi services registry with Spring DM <osgi:service.
  • fr.opensagres.data.injector : OSGi bundle Data Injector which hosts a Spring file which declares a DataInjector in a Spring bean. This DataInjector consumes the UserService injected by Spring which is retrieved from the OSGi services registry with Spring DM <osgi:reference and call UserService#saveUser(User user) to inject User data.
  • fr.opensagres.simpleclient : OSGi bundle simple client which hosts a Spring file which declares a thread in a Spring bean. This thread consumes the UserService injected by Spring which is retrieved from the OSGi services registry with Spring DM <osgi:reference.
  • fr.opensagres.config.log4j : OSGi fragment which configures log4j.
  • TargetPlatform: simple project which hosts the Spring DM JARS, the target definition and launch.

To use this zip, unzip it :

  1. import those projects in a workspace.
  2. open the TargetPlatform/eclipsespring.target file and click on Set as Target Platform.
  3. select TargetPlatform/launch/Simple OSGi client.launch – Mock Dao to test the launch with Mock Dao and Run it.
  4. select TargetPlatform/launch/Simple OSGi client.launch – JPA Dao to test the launch with JPA Dao and Run it.

Bundles – Spring Data JPA

Before starting this article, we modify the TargetPlatform/launch/Simple OSGi client.launch :

  • rename this launch to Simple OSGi Client – Mock Dao.
  • unselect the option "Add new workspace bundles to this launch configuration automatically", because we will create new JPA bundles and we want not to include it in the MockDao launch.

Domain Bundle

At first we annotate our domain fr.opensagres.domain.User class with JPA annotation.

User class

Modify the fr.opensagres.domain.User class like this:

package fr.opensagres.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;

@Entity(name = "T_USER")
public class User {

	@Id
	@GeneratedValue(generator = "GEN_USER")
	@SequenceGenerator(name = "GEN_USER", sequenceName = "SEQ_USER")
	private Long id;

	@Column
	private String firstName;

	@Column
	private String lastName;

	public Long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

}

NOTE: to avoid having this (non blocking) errors with sequence as soon as the Database is created :

Internal Exception: java.sql.SQLException: Table/View 'SEQUENCE' already exists in Schema 'APP'.
Error Code: 30000
Call: CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))

The @SequenceGenerator is used.

Rule 6: import annotation package as optional (MANIFEST.MF)

In the META-INF/MANIFEST-MF of the fr.opensagres.domain bundle:

  • import the javax.persistence package as optional.

Why importing JPA annotation as optional? The answer is that in some context, you need not JPA annotation (ex: for the MockUserDao).
To understand that, remove the optional resolution, open the Simple OSGi client.launch and click on Validate Bundles button to see the error about import package :

Set the as optional the javax.persistence package and click on Validate Bundles to check you have none error.

Here the full content of this MANIFEST.MF:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Domain
Bundle-SymbolicName: fr.opensagres.domain
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Export-Package: fr.opensagres.domain
Import-Package: javax.persistence;resolution:=optional

Dao JPA Implementation Bundle

Here we will create the JPA Dao Implementation :

We will use Spring Data JPA to do that (you can notice in the below screenshot that there is none Java class like JpaUserDao).

Create OSGi bundle fr.opensagres.dao.jpa.

persistence.xml

Create the JPA META-INF/persistence.xml like this:

<?xml version="1.0"  encoding="UTF-8"?>
<persistence  xmlns="http://java.sun.com/xml/ns/persistence"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              version="2.0"  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence

http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

	<persistence-unit name="userUnit" transaction-type="RESOURCE_LOCAL">
		<class>fr.opensagres.domain.User</class>
	</persistence-unit>

</persistence>

module-context.xml

Create the META-INF/spring/module-context.xml like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:util="http://www.springframework.org/schema/util"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa"
	xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
			http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
			http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd

http://www.springframework.org/schema/data/jpa


http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

	<context:property-placeholder
		location="classpath*:META-INF/config/config.properties" />

	<bean id="jpaDialect" class="${config.jpa.dialect}" />

	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="persistenceUnitName" value="userUnit" />
		<property name="dataSource" ref="dataSource" />
		<property name="jpaDialect" ref="jpaDialect" />
		<property name="jpaProperties">
			<util:properties location="classpath:META-INF/config/jta.properties" />
		</property>

		<property name="jpaVendorAdapter">
			<bean class="${config.jpa.vendorAdapter}">
				<property name="databasePlatform" value="${config.db.platform}" />
			</bean>
		</property>

	</bean>

	<!-- Transaction Manager -->
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
		p:entityManagerFactory-ref="entityManagerFactory">
		<property name="jpaDialect" ref="jpaDialect" />
	</bean>

	<tx:annotation-driven transaction-manager="transactionManager" />

	<!-- Spring Data JPA-->
	<jpa:repositories base-package="fr.opensagres.dao">
		<jpa:repository id="userDao" />
	</jpa:repositories>

</beans>

Here explanation of this Spring file :

  1. At first we load a properties file META-INF/config/config.properties :
    <context:property-placeholder location="classpath*:META-INF/config/config.properties" />
    

    means that the bundle load 3 properties from META-INF/config/config.properties.

    • config.db.platform: the database platform. (ex: config.db.platform=org.eclipse.persistence.platform.database.DerbyPlatform).
    • config.jpa.vendorAdapter: the JPA VendorAdapter. (ex: config.jpa.vendorAdapter=org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter).
    • config.jpa.dialect: the JPA Dialect. (ex: config.jpa.dialect=org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect).

    This file is not stored in the fr.opensagres.dao.jpa bundle it is stored in an OSGi fragment fr.opensagres.dao.jpa.eclipselink which host this config.properties file to configure the JPA with EclipseLink and Derby dialect. Using a config.properties file in OSGi context it’s a good idea because the JPA Dao Implementation bundle fr.opensagres.dao.jpa have none dependency to the

    • JPA Implementation. For instance if you wish using Hibernate you can create an other OSGi fragment with config.properties which configures the Hibernate dialect, the Vendor Adapter, etc…
    • Database dialect.
  2. After we create the bean jpaDialect like this :
    <bean id="jpaDialect" class="${config.jpa.dialect}" />
    

    here the jpaDialect bean is created by using the property config.jpa.dialect (ex: config.jpa.dialect=org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect) of the config.properties file.

  3. The entity manager is created like this:
    <bean id="entityManagerFactory"
    	class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    	<property name="persistenceUnitName" value="userUnit" />
    	<property name="dataSource" ref="dataSource" />
    	<property name="jpaDialect" ref="jpaDialect" />
    	<property name="jpaProperties">
    		<util:properties location="classpath:META-INF/config/jta.properties" />
    	</property>
    		<property name="jpaVendorAdapter">
    		<bean class="${config.jpa.vendorAdapter}">
    			<property name="databasePlatform" value="${config.db.platform}" />
    		</bean>
    	</property>
    </bean>
    

    with those properties :

    • the persistenceUnitName property is setted like this:
      <property name="persistenceUnitName" value="userUnit" />

      to reference the persistent unit of the META-INF/persistence.xml

    • the dataSource property is setted like this:
      <property name="dataSource" ref="dataSource" />

      to reference a dataSource bean that we will retrieves from OSGi registry services (see module-osgi-context.xml).

    • the jpaDialect property is setted like this:
      <property name="jpaDialect" ref="jpaDialect" />

      to reference the jpaDialect which was created by using theconfig.jpa.dialectproperty .

    • The JPA properties is configured by a file config/jta.properties that it will be stored too in the OSGi fragment (like config.properties).
      <property name="jpaProperties">
      	<util:properties location="classpath:META-INF/config/jta.properties" />
      </property>
      
    • The JPA vendor adapter is configured by using the 2 properties config.jpa.vendorAdapter and config.db.platform of the config.properties file.
      <property name="jpaVendorAdapter">
      	<bean class="${config.jpa.vendorAdapter}">
      		<property name="databasePlatform" value="${config.db.platform}" />
      	</bean>
      </property>
      
  4. The transaction manager is configured like this :
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
    	p:entityManagerFactory-ref="entityManagerFactory">
    	<property name="jpaDialect" ref="jpaDialect" />
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager" />
    
  5. here Spring Data JPA is used to implement on runtime the JPA Dao:
    <jpa:repositories base-package="fr.opensagres.dao">
    	<jpa:repository id="userDao" />
    </jpa:repositories>
    

    You must fill:

    • the base package of the Dao fr.opensagres.dao.
    • the id of the jpa:repository which will be used to create an instance on runtime of JPA UserDao and register as Spring bean with the userDao id.

module-osgi-context.xml

Here we must configure beans that we must publish/consume from the OSgi registry services:

  • retrieves a dataSource bean from the OSGi registry services.
  • publish the JPA UserDao created at runtime by Spring Data JPA (with id=userDao).

Create the META-INF/spring/module-osgi-context.xml like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi"
	xsi:schemaLocation="http://www.springframework.org/schema/osgi  

http://www.springframework.org/schema/osgi/spring-osgi-1.0.xsd


http://www.springframework.org/schema/beans


http://www.springframework.org/schema/beans/spring-beans.xsd">

	<osgi:reference id="dataSource" interface="javax.sql.DataSource" />

	<osgi:service ref="userDao" interface="fr.opensagres.dao.UserDao" />

</beans>      

MANIFEST.MF

Rule7: Spring & Import-Package

MANIFEST.MF must be modified to import several packages. I find it was the more hard task to do when we have integrated Spring Data JPA in our project.

The difficulty to know which import packages must be done is that the bundle have none Java classes, so none compilation errors.

Here several rules that I’m using to know which package must be imported :

  1. use package of declared Spring bean/@class. For instance if you declare this bean :
    <bean id="entityManagerFactory"
    		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    

    you must import the org.springframework.orm.jpa package.

  2. import the domain and dao package for JPA DAO bundle implementation.
  3. when jpa:repository is used, the well Spring Data packages must be imported.
  4. for the other packages, the only solution I have found it’s to run the launch and see the ClassNotFoundException. We will see a sample in Test with missing import package section.

Modify the META-INF/MANIFEST-MF of the fr.opensagres.dao.jpa bundle like this:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Dao JPA Implementation
Bundle-SymbolicName: fr.opensagres.dao.jpa
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: fr.opensagres.dao,
 fr.opensagres.domain,
 javax.persistence,
 javax.persistence.criteria,
 javax.persistence.metamodel,
 javax.persistence.spi,
 org.aopalliance.aop,
 org.springframework.aop,
 org.springframework.aop.framework,
 org.springframework.data.domain,
 org.springframework.data.jpa.repository.support,
 org.springframework.data.repository,
 org.springframework.data.repository.core.support,
 org.springframework.orm.jpa

JPA EclipseLink&Derby Configuration Fragment

Here we will create the OSGi fragment fr.opensagres.dao.jpa.eclipselink linked to the OSGi bundle fr.opensagres.dao.jpa to configure JPA:

  • using EclipseLink as JPA Implementation.
  • using Derby as database dialect.

config/config.properties

Create the config/config.properties like this:

 
db.platform=org.eclipse.persistence.platform.database.DerbyPlatform
jpaVendorAdapter=org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter
jpaDialect=org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect

config/jta.properties

Create the config/jta.properties like this:

 
eclipselink.ddl-generation=drop-and-create-tables
eclipselink.ddl-generation.output-mode=both
eclipselink.target-database=org.eclipse.persistence.platform.database.DerbyPlatform
eclipselink.weaving=false

This configuration will create the Derby Database on the first time of using of JPA EntityManager.

MANIFEST.MF

Modify the META-INF/MANIFEST-MF of the fr.opensagres.dao.jpa.eclispelink fragment like this:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: JPA EclipseLink&Derby Configuration
Bundle-SymbolicName: fr.opensagres.dao.jpa.eclipselink
Bundle-Version: 1.0.0.qualifier
Fragment-Host: fr.opensagres.dao.jpa;bundle-version="1.0.0.qualifier"
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: org.apache.derby.jdbc,
 org.springframework.orm.jpa.vendor;version="3.0.5.RELEASE"
Require-Bundle: org.eclipse.persistence.antlr;bundle-version="2.3.0",
 org.eclipse.persistence.asm;bundle-version="2.3.0",
 org.eclipse.persistence.core;bundle-version="2.3.0",
 org.eclipse.persistence.jpa;bundle-version="2.3.0"

Datasource Bundle

The bean of the fr.opensagres.dao.jpa needs a dataSource bean. We will create fr.opensagres.data.datasource bundle which will publish in teh OSGi services registry a Datasource of the Derby Database.

Create OSGi bundle fr.opensagres.data.datasource.

module-context.xml

Create the META-INF/spring/module-context.xml like this :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
			http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">

	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" />
		<property name="url" value="jdbc:derby:target/derbydb;create=true" />
		<property name="initialSize" value="5" />
		<property name="maxActive" value="50" />
	</bean>

</beans>

Here we create a datasource with Commons DBCP on a Derby database.

module-osgi-context.xml

Create the META-INF/spring/module-context.xml to publish the datasource like this :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi"
	xsi:schemaLocation="http://www.springframework.org/schema/osgi  

http://www.springframework.org/schema/osgi/spring-osgi-1.0.xsd


http://www.springframework.org/schema/beans


http://www.springframework.org/schema/beans/spring-beans.xsd">

	<osgi:service ref="dataSource" interface="javax.sql.DataSource" />

</beans>           

MANIFEST.MF

Modify the META-INF/MANIFEST-MF of the fr.opensagres.data.datasource bundle like this:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Datasource
Bundle-SymbolicName: fr.opensagres.data.datasource
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: org.apache.commons.dbcp

Run

At this step we can create the OSGi launch to use the JPA Dao Implementation. To do that duplicate the Simple OSGi Client – Mock Dao:

Rename the duplicated launch to Simple OSGi Client – JPA Dao:

  • unselect the fr.opensagres.dao.mock.
  • select the fr.opensagres.dao.jpa and set Auto-Start to true.
  • select the fr.opensagres.dao.jpa.eclipselink.
  • select the fr.opensagres.data.datasource and set Auto-Start to true.
  • click on Add Required Bundles button to add required bundles.

If you run the launch, you will see on the console:

...
org.springframework.beans.factory.support.DefaultListableBeanFactory@1c18a4c: defining beans [DataInjector,userService]; root of factory hierarchy
org.springframework.osgi.service.ServiceUnavailableException: service matching filter=[(objectClass=fr.opensagres.dao.UserDao)] unavailable

which means that the DataInjector bean of the fr.opensagres.data.injector consumes UserService but UserDao is not available (the JPA UserDao created by Spring Data JPA).
But you will see after:

Call: CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))
Query: DataModifyQuery(sql="CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))")
4453 [SpringOsgiExtenderThread-10] INFO  org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean  - Publishing service under classes [{fr.opensagres.dao.UserDao}]

which means that the JPA UserDao and publish on OSGi services registry was created with success.

So the problem here is that the creation of the JPA UserDao takes times and DataInjector tries to consume the UserService before than JPA UserDao is created and published.

The problem is because of cardinality="0..1" and timeout="1000" used in the Spring file of the bundle fr.opensagres.services.impl:

<!-- Consume UserDao from the OSGi services registry -->
<osgi:reference id="userDao" interface="fr.opensagres.dao.UserDao" cardinality="0..1" timeout="1000" />

Modify the fr.opensagres.services.impl/META-INF/spring/module-osgi-context.xml like this:

<!-- Consume UserDao from the OSGi services registry -->
<osgi:reference id="userDao" interface="fr.opensagres.dao.UserDao" />

Run the launch and you will see on the console:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DataInjector' defined in URL [bundleentry://16.fwk12097592/META-INF/spring/module-context.xml]: Invocation of init method failed; nested exception is org.springframework.osgi.service.ServiceUnavailableException: service matching filter=[(objectClass=fr.opensagres.services.UserService)] unavailable
...
Caused by: org.springframework.osgi.service.ServiceUnavailableException: service matching filter=[(objectClass=fr.opensagres.services.UserService)] unavailable

Here the problem is that UserService is not available because the JPA UserDao takes times ans UserService is not published when DataInjector tries to consume it. The problem is because of cardinality="0..1" and timeout="1000" used in the Spring file of the bundle fr.opensagres.data.injector:

<!-- Consume UserService from the OSGi services registry -->
<osgi:reference id="userService" interface="fr.opensagres.services.UserService" cardinality="0..1" timeout="1000" />

Modify the fr.opensagres.data.injector/META-INF/spring/module-osgi-context.xml like this:

<!-- Consume UserService from the OSGi services registry -->
<osgi:reference id="userService" interface="fr.opensagres.services.UserService" />

Run the OSGi launch, you will see at first on the console the error :

org.springframework.osgi.service.ServiceUnavailableException: service matching filter=[(objectClass=fr.opensagres.services.UserService)] unavailable
...
	at fr.opensagres.simpleclient.FindAllUsersThread.displayUsers(FindAllUsersThread.java:45)
	at fr.opensagres.simpleclient.FindAllUsersThread.run(FindAllUsersThread.java:29)

This error occurs teh first time when the FindAllUsersThread thread tries to consume UserService (JPA UserDao creation takes time).

After you will see on the console :

...
Call: CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))
...
User [Angelo Zerr]
User [Pascal Leclercq]
User [Amine Bousta]
User [Mickael Baron]
User [Jawher Moussa]
User [Arnaud Cogoluegnes]
User [Lars Vogel]
User [Olivier Gierke]
User [Tom Schindl]
User [Wim Jongman]

The Database is created and the FindAllUsersThread thread can consumes the UserService which use the JPA User Dao!

Test with missing import package

Here we will see a sample with ClassNotFoundException when import packag eis not done correctly. Remove the import package org.aopalliance.aop in the MANIFEST.MF of the bundle fr.opensagres.dao.jpa and run the launch:

You will see on the console this error :

Exception in thread "SpringOsgiExtenderThread-8" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean#0': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao': FactoryBean threw exception on object creation; nested exception is java.lang.NoClassDefFoundError: org.aopalliance.aop.Advice not found from bundle [fr.opensagres.dao.jpa]

This error means that you must import the package org.aopalliance.aop in the fr.opensagres.dao.jpa bundle.

Conclusion

In this article we have implemented UserDao with JPA by using Spring Data JPA, EclipseLink and Derby. The big difficulty to do that in an OSGi context is to import the well packages in the well bundles. We have seen how to Spring Data JPA avoids coding the implementation of the DAO with JPA just by declaring the jpa:repository (very easy!) :

<!-- Spring Data JPA-->
<jpa:repositories base-package="fr.opensagres.dao">
	<jpa:repository id="userDao" />
</jpa:repositories>

In the next article [step7], we will see how it’s very easy with Spring Data JPA to :

  • manage pagination and sort.
  • manage service with some basic criteria.
About these ads
  1. Amod
    mai 18, 2012 à 9:07   | #1

    Hi Angelo ,

    Validate Bundles throws an error of missing constraint : Import Package : javax.annotation; version ="0.0.0" for spring-data-jpa bundle

    any idea why this could occur ?

    Thanks and Regards,
    Amod

    • mai 18, 2012 à 10:37   | #2

      Hi Armod,

      I have notice this problem too, but I don’t know why? But it works.
      If you discover the problem, don’t hesitate to post message.

      Many Thank’s

      Regards Angelo

  2. juin 8, 2012 à 8:17   | #3

    Hi Angelo,
    Same probleme when validating Bundles from Run Configuration.
    Thanks and Regards.
    gehrard

    • juin 8, 2012 à 12:19   | #4

      Hi Gehrard,
      There is the javax.annotation bundle which we must download. I will search where I can download with maven. If you find it, don’t hesitate to tell me.
      Many Thank’s.

  3. juin 8, 2012 à 10:29   | #5

    Hi Angelo
    I met a problem when creatiing data base (SEQUENCE allready exists in schema ….). I have updated the domain mapping class as :
    - – - –
    @Entity(name = "T_USER")
    public class User {

    @Id
    // @GeneratedValue
    @GeneratedValue(generator = "User_Gen")
    @SequenceGenerator(name = "User_Gen", sequenceName = "User_Sequence")
    private Long id;
    - – - -

    Thanks and Regards

    • juin 8, 2012 à 12:23   | #6

      Hi Gehrard,
      Many thank’s for your comment. I will try to modify every my articles with your suggestion (I just must test it before). Goal of my articles is not focused on JPA annotations (so it will have some errors about JPA as you have seen) but rather about the description of the architecture of "Eclipse RCP/RAP with Spring DM, Spring Data JPA and Remoting ".

      Regards Angelo

      • juin 8, 2012 à 3:44   | #7

        Hi Gehrard,

        I have updated this article with your suggestion with @SequenceGenerator and fix problem with "Validate Bundles throws an error of missing constraint : Import Package : javax.annotation; version =”0.0.0″ for spring-data-jpa bundl" by adding the geronimo.annotation_1.1_spec bundle ‘see pom.xml in the step5).

        Regards Angelo

  4. Eugen
    août 1, 2012 à 8:20   | #8

    For those who want to use a PostgreSQL database instead of Derby:
    - In "jta.properties":
    eclipselink.target-database=org.eclipse.persistence.platform.database.PostgreSQLPlatform

    - In "config.properties":
    config.db.platform=org.eclipse.persistence.platform.database.PostgreSQLPlatform

    - In "pom.xml" add:

    org.postgresql
    com.springsource.org.postgresql.jdbc4
    ${database.postgresql}

    - Then refresh Maven dependencies, TargetPlatform, and RunConfiguration ("Add required Bundles"). That should be it.

    @Angelo: Great tutorial!

  5. Ralf
    juillet 16, 2013 à 11:42   | #10

    Hi Angelo, many thanks for this good tutorial. One question about database connection: How could I achieve that the end user can change the database and the user credentials? I.e., I’ve an application which supports more than one database (Derby, HSQL, MySQL and so on). The user should be able to change the DB connection before the application launches the first time. Any help is appreciated. Thanks, Ralf.

  6. Emile
    avril 2, 2014 à 3:11   | #11

    Hi Angelo,
    Il have some trouble with retreiving data from derby database. I launch the configuration without problem but no data is dsplayed. I juste have "Start Thread FindAllUsersThread" and when i enter in debug mode, the injector creates users with userService service but for retreiving users, userDoa.findAll() always return an empty list.
    There is none error message on my osgi console.
    It seems like i omit a commit command. Any idea will be appreciated.
    Is there a way to see the data in derby db on eclipse?
    Thanks in advance

  1. avril 12, 2012 à 4:14   | #1
  2. avril 13, 2012 à 12:38   | #2

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

Suivre

Recevez les nouvelles publications par mail.

Joignez-vous à 169 followers

%d bloggers like this: