Overblog Suivre ce blog
Administration Créer mon blog
20 mai 2011 5 20 /05 /mai /2011 13:27

hibernate-icon.jpeg

 

Why a NonUniqueObjectException is thrown ? 

 

A NonUniqueObjetException is thrown because hibernate is not able to decide what version of an entity it has to persist.

 

In this case, it will throw something like this :

org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.davidgimelle.hibernate.examples.Role#1]

at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:590)

at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:284)

at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)

at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89)

at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)

at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)

at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)

at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)

at com.davidgimelle.hibernate.examples.TestLostSession.commitADetachedObjetThrowAnNonUniqueObjectException(TestLostSession.java:53)

This exception has been thrown because hibernate has tried to persist 2 instances of the same entity, with the same id but not the same content.

For example : role1(id:1, name:"admin") and role2(id:1,name"user")

 

Usually that happens when an entity is persisted and detached from the session. Another instance of this entity is requested to hibernate. This second instance stayed attached to the session. The first instance is modified.

 

When hibernate persit the second instance, it is not able to choose what is the correct content to persist and throw an NonUniqueObjectException. 

 

It easier to understand with an example. This piece of code will throw and display an NonUniqueObjectException :

 

Role role = new Role().withName("Customer");

 

 //Persist a first Role Entity and close the session

Session openSession = sessionFactory.openSession();

Transaction beginTransaction = openSession.beginTransaction();

openSession.persist(role);

beginTransaction.commit();

openSession.close();

 //Now role is detached from the session

 

 //change a value in this role

role.setName("new role Name");

 

 //Open a new session

openSession =sessionFactory.openSession();

 

 //Instanciation of the same role from the new session

Role roleFromDB= (Role) openSession.get(Role.class, role.getId());

 //Now role and roleFromDB have the same id, but role is detached

 

Transaction beginTransaction2 = openSession.beginTransaction();

 

 

 //The next line will throw an exception

try{

 //Save role and throw an exception

openSession.saveOrUpdate(role);

 

//This line will be never executed

beginTransaction2.commit();

Assert.fail();// Fail this test if this line is reached

}

catch(NonUniqueObjectException nuoe){

//Display this exception

nuoe.printStackTrace();

}

openSession.close();

 

You can find a complet maven project able to run this exemple in a Junit test at http://www.davidgimelle.com/src/hibernate_examples_dg-src.1.1.1-SNAPSHOT.zip 

 

References    

- SaveOrUpdate versus Merge : http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate

- Saving detached entities : http://blog.xebia.com/2009/03/jpa-implementation-patterns-saving-detached-entities

Repost 0
Published by David Gimelle - dans Java
commenter cet article
12 juin 2010 6 12 /06 /juin /2010 10:00

resteasylogo.jpg

Voici un mini tutorial sur JBoss RESTEasy, l'implementation de JAX-RS 1.2.GA de JBoss avec le serveur JBoss 5.1. Ce mini tutorial est directement inspiré de l'excellent tutoriel de Damien Gouyette : Exposer un service crud RESTul avec JBoss RESTasy  http://dgouyette.developpez.com/tutoriels/java/exposer-service-crud-restful-avec-jboss-resteasy/

 

J'ai eu quelques misères à en faire fonctionner les sources et à récupérer les bonnes versions des bibliothèques sous maven avec netbeans,  aussi en m'inspirant des sources de Damien Gouyette j'ai eu l'idée de me faire un mini projet pilote, un genre de CRUD sans le C ni le U, ni le D, bref juste un READ, c a d un GET dans le monde REST.

 

Et finalement j'en fait un mini tutorial que je poste sur mon blog. Les sources complètes du projet sous maven sont disponible à la fin de l'article dans un zip.

 

L'objet de tutorial est de faire un appel Rest GET de la forme : http://localhost:8080/RestEasyTutorial/rest/hello/bill .

il s'agit de l'appel d'une des ressources des services REST du site http://localhost:8080/RestEasyTutorial . La ressource se nomme hello et l'identifiant est bill dans cet exemple. Cet appel va retourner hello bill

 

La déclaration des ressources se fait via des annotations dans une classe Java :

 

package com.davidgimelle.tutorial.resteasyread;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;

@Path("hello")
public class HelloWorld {

    @GET
    @Path("/{qui}")
    public Response echoService(@PathParam("qui") String message) {
        return Response.status(200).entity("hello "+message).build();
    }

}

 

- L'annotation @Path sur la classe détermine le nom de la ressource.

- @GET précise quelle méthode sera appelée en cas de requête Http GET sur cette ressource.

- @Path sur la méthode précise la forme des paramètres sur la ressource

- @PathParam précise quel paramètre va être utilisé dans la méthode

 

 

Ces classes de ressources REST doivent être déployées dans une application web. Cette application web nécessite un fichier web.xml qui va définir comment est configurer RESTEasy :


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>RestEasyTutorial</display-name>
   

   <context-param>
      <param-name>resteasy.scan</param-name>
      <param-value>true</param-value>
   </context-param>

    <context-param>
        <param-name>resteasy.servlet.mapping.prefix</param-name>
        <param-value>/rest</param-value>
    </context-param>

    <listener>
        <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
    </listener>

    <servlet>
        <servlet-name>Resteasy</servlet-name>
        <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Resteasy</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

</web-app>

 

- Le context-param resteasy.scan à true signifie que les sources du war vont être scannées à la recherche des annotations RESTEasy pour publier les ressources automatiquement lors du démarrage de l'application.

- Le servlet-mapping RESTEasy avec la valeur /rest/* précise que tous les appels de cette forme sont à destination de RESTEasy.

 

 

Les dépendances maven nécessaires au bon fonctionnements de RESTEasy sont les suivantes :

 

    <repositories>
        <repository>
            <id>jboss</id>
            <url>http://repository.jboss.com/maven2/</url>
        </repository>
    </repositories>

    <dependencies>


        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxrs</artifactId>
            <version>1.2.GA</version>
        </dependency>


    </dependencies>

 

Le repository http://repository.jboss.com/maven2/ permet de télécharger la dépendance resteasy-jaxrs.

 

 

Ce mini tuto est terminé. Vous pouvez tétécharger les sources du projet maven complet de ce mini tuto ici.

 

N'oubliez pas de suivre le tutorial de Damien Gouyette pour bien comprendre comment fonctionne REST, comment faire un CRUD et surtout comment faire des tests automatisées des services RESTEasy. On ne test jamais assez. !

 

 

Sources : http://www.davidgimelle.com/src/RestEasyReadTutorial-src.zip

 

Testé le 10 juin 2010 avec :

resteasy-jaxrs 1.2.GA, JBoss 5.1.0.GA, Java jdk 1.5_20, maven 2.0.9 et netbeans 6.7.1

 

Références :

Le tutorial de Damien Gouyette : http://dgouyette.developpez.com/tutoriels/java/exposer-service-crud-restful-avec-jboss-resteasy/

JBoss RestEasy : http://www.jboss.org/resteasy

Rest dans wikipedia : http://en.wikipedia.org/wiki/Representational_State_Transfer

Pour acheter des objets RestEasy : http://www.cafepress.co.uk/jbossorg/7097895

 

Repost 0
Published by David Gimelle - dans Java
commenter cet article
29 mai 2010 6 29 /05 /mai /2010 14:35

derby-logo-web.png

 

Voici un exemple de déclaration d'un datasource minimaliste pour une database Derby sous JBoss 4.

 

Pour déclarer un datasource derby, il faut :

- Copier dans le repertoire lib de l'instance Jboss la libraire derbyClient.jar, par exemple dans server\default\lib

- Déclarer un fichier derby-ds.xml dans le repertoire de déploiment, par exemple dans server\default\deploy

 

et c'est fini. :)

 

Voici le fichier derby-ds.xml:

 

<?xml version="1.0" encoding="UTF-8"?>
 
<datasources>
    <local-tx-datasource>
        <jndi-name>MyDb</jndi-name>
        <connection-url>jdbc:derby://localhost:1527/myLittleDb;create=true</connection-url>
        <driver-class>org.apache.derby.jdbc.ClientDriver</driver-class>
        <user-name>admin</user-name>
        <password>admin</password>
        <min-pool-size>5</min-pool-size>
        <max-pool-size>20</max-pool-size>
        <idle-timeout-minutes>5</idle-timeout-minutes>
        <track-statements/>
    </local-tx-datasource>
</datasources>

 

 

Référence : http://community.jboss.org/wiki/SetUpADerbyDatasource

Le client derby : http://repo1.maven.org/maven2/org/apache/derby/derbyclient

Testé avec : Java 5, Jboss 4.2.3 et derby 10.5.3.0_1

 

 

Repost 0
Published by David Gimelle - dans Java
commenter cet article

Summary

  • : GetJ2ee -Java development
  • : Articles about Java and EE
  • Contact

Profil

  • David Gimelle
  • Java Developer for more 10 years. I worked in France, Canada and Switzerland. I am contractor in London since 2010.
  • Java Developer for more 10 years. I worked in France, Canada and Switzerland. I am contractor in London since 2010.

Contact

You can contact me here

or by Twitter

Search

Archives