-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Using EntityMode.DOM4J with just Annotations
PostPosted: Thu Dec 28, 2006 10:41 am 
Newbie

Joined: Fri Jul 21, 2006 7:20 am
Posts: 15
Hibernate version: 3.2.1 GA

I want to serialize my Business objects (POJO's) to XML. Reading chapter 18 of the documentation explained how to do this, but it uses an XML-mapping file (which I'd rather not use, since I prefer annotations).

My first question is:

How to retrieve an XML representation of a POJO when I only use annotated classes?

If I try this:

Code:
        Session session = HibernateUtil.getSession();
        Session dom4jSession = session.getSession( EntityMode.DOM4J );

        Element userXML = (Element)dom4jSession.load( Mask.class, 1l );

        try {
            OutputFormat format = OutputFormat.createPrettyPrint();
            XMLWriter writer = new XMLWriter( System.out, format );
            writer.write( userXML );
        } catch( IOException ex ) {
            throw new RuntimeException( ex );
        }


I end up with this exception:

Code:
Exception in thread "main" org.hibernate.HibernateException: No tuplizer found for entity-mode [dom4j]
   at org.hibernate.tuple.EntityModeToTuplizerMapping.getTuplizer(EntityModeToTuplizerMapping.java:68)
   at org.hibernate.tuple.entity.EntityMetamodel.getTuplizer(EntityMetamodel.java:100)
   at org.hibernate.persister.entity.AbstractEntityPersister.createProxy(AbstractEntityPersister.java:3403)
   at org.hibernate.event.def.DefaultLoadEventListener.createProxyIfNecessary(DefaultLoadEventListener.java:257)
   at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:191)
   at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)
   at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
   at org.hibernate.impl.SessionImpl.load(SessionImpl.java:795)
   at org.hibernate.impl.SessionImpl.load(SessionImpl.java:788)
   at com.example.test.Tester.main(Tester.java:21)


This is my hibernate.cfg.xml:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"   "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

   <!--  Test commit over SSH -->
   <session-factory>
      <property name="connection.driver_class">org.gjt.mm.mysql.Driver</property>
      <property name="connection.password">passwd</property>
      <property name="connection.url">jdbc:mysql://localhost/processes</property>
      <property name="connection.username">user</property>
   </session-factory>
   
</hibernate-configuration>


But the testing code works when I add this line to the above configuration:

Code:
      <mapping resource="Mask.hbm.xml"/>


The content of Mask.hbm.xml is as follows:

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping package="com.example.dbo" default-access="field">

   <class name="Mask">
       <id name="id" type="long">
         <generator class="native"/>
      </id>
       <property name="maskName"/>
   </class>
   
</hibernate-mapping>


And to be fully clear, this is my HibernateUtil.java

Code:
package com.example.util.hibernate;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

import com.example.dbo.Mask;

public class HibernateUtil
{
    private static final SessionFactory sessionFactory;
    private static Session              session = null;

    static
    {
        try
        {
            // Create the SessionFactory from hibernate.cfg.xml
            sessionFactory = new AnnotationConfiguration()
                .addPackage( "com.example.dbo" )
                .addAnnotatedClass( Mask.class )
                .configure()
                .buildSessionFactory();
        }
        catch( Throwable ex )
        {
            System.err.println( "Initial SessionFactory creation failed." + ex );
            throw new ExceptionInInitializerError( ex );
        }
    }

    public static Session getSession()
    {
        if( session == null )
            session = sessionFactory.openSession();

        return session;
    }
}


I have read chapter 3.4.2 from the book "Java persistance with Hibernate" but that does not make it clear if I can just use annotations or if I HAVE
to have .hbm.xml files in order to be able to use the EntityMode.DOM4J session.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 28, 2006 3:45 pm 
Newbie

Joined: Fri Jul 21, 2006 7:20 am
Posts: 15
I found that during the secondPassCompile() of the AnnotationConfiguration class, the processArtifactsOfType(String artifact) is called only for .hbm files. This in turn invokes the HbmBinder.bindRoot() method which eventually invokes the setNodeName on the persistant class.

When the Dom4jComponentTuplizer is created, it checks for this nodeName. And this nodeName is null when I do not use a .hbm.xml mapping file.

This leads me to the conclusion that I have to create .hbm.xml files for every entity that I want to be able to transform into XML. (If I do not use .hbm.xml files this results in a Exception in thread "main" org.hibernate.HibernateException: No tuplizer found for entity-mode [dom4j])

I hope I am wrong and that there is a way to achieve this using just annotations.

It should be possible to get a clean XML representation of an annotated class without using .hbm.xml mapping files (By using sensible defaults, such as the classname and fieldnames).

I tried using Xstream but since this uses reflection I end up with hibernated-xml ouput (Including the Lazy bags and collections)


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 30, 2006 8:44 am 
Newbie

Joined: Fri Jul 21, 2006 7:20 am
Posts: 15
Okay, I've managed to get a decent XML output by creating a .hbm.xml mapping file that describes the properties of my business entities. So now I can use the DOM4J entitymode.

In other words, I am doing my mapping work twice; annotations and a mapping file.

I read a comment of one of the hibernate-team members, saying that it is strange to use annotation information if you do not use POJO entity mode.

This is true, BUT, when people ARE using mixed mode (Both POJO's and DOM4J entities) hibernate should use the information that can be obtained from the annotations that are in the POJO's. This is just a matter of Abstraction;

An AbstractMapping class can hold mapping information that can be supplied by an AnnotationMapping and/or an XMLMapping. So Hibernate can just look at this AbstractMapping, no matter what method is used to supply the mapping information.

I think this would be an improvement to hibernate and I am willing to contribute to this feature.

Edit: Maybe I am stating the obvious but you can't mix annotations and hbm.xml files. So a business entity is either completely mapped using annotations or completely mapped by a hbm.xml file.
So if you want to use DOM4J mode, you MUST use hbm.xml mappings.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 02, 2007 2:03 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Hi,
I believe I forgot to set up an entityNode name in AnnotationBinder (and co). Will you consider providing an patch (ie set up this value like it is done un HbmBinder)?

If not, open a JIRA issue, so that I don't forget.

Thanks

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 02, 2007 4:42 pm 
Newbie

Joined: Fri Jul 21, 2006 7:20 am
Posts: 15
emmanuel wrote:
If not, open a JIRA issue, so that I don't forget.
Thanks


I opened a JIRA issue, because I am not very into the hibernate code and I think you can fix this 10 times faster than I will be able to do.

Bug report: http://opensource.atlassian.com/projects/hibernate/browse/ANN-517


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 04, 2007 8:04 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
yes, but I can't work more than 24h / day :-)

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 05, 2007 6:43 am 
Newbie

Joined: Fri Jul 21, 2006 7:20 am
Posts: 15
Okay, I tried it myself and started trying to compile the HibernateExt project but getting that to work is a complete hell. It ends with 49 compile errors when I just run build.bat

Checking it in a Eclipse project and using the Ant build.xml files does not get me further as well. (Is there a library missing or are there people that have no problems to commit not-compiling projects into subversion?)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 05, 2007 12:13 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
No I never commit something not functional, but I'm not proud of the compile process.

Have a look at
http://www.hibernate.org/30.html
I've just made a tutorial on how to compile.

Be sure to use branch_3_2 from SVN.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 05, 2007 5:20 pm 
Newbie

Joined: Fri Jul 21, 2006 7:20 am
Posts: 15
emmanuel wrote:
Have a look at
http://www.hibernate.org/30.html
I've just made a tutorial on how to compile.

Be sure to use branch_3_2 from SVN.


Thanks, using branch_3_2 helps getting rid of the compile errors.

I would expect the tutorial at this URL: http://www.hibernate.org/268.html
or at both places :)

I added a line in AnnotationBinder.java in the bindClass() method 'persistantClass.setEntityName( entityAnn.name() );' but that didn't help. I'm going to the pub right now and maybe I will see this weekend if I'm able to get the darn thing finally done.

(Suggestions are more than welcome!)


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 06, 2007 8:27 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
I've cross referenced from both pages, thanks.
You should do something like
entity.setNodeName(...)
property.setNodeName(...)
collection.setNodeName(...)

setEntityName should not be change I think

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 07, 2007 3:36 pm 
Newbie

Joined: Fri Jul 21, 2006 7:20 am
Posts: 15
Although the code in HbmBinder.java is easier to read, I managed to get this darn thing working! I added a line in EntityBinder, PropertyBinder and CollectionBinder (as I think it belongs there). I'll attach the patch in JIRA.

Some thoughts:
- It is not possible to specify a different nodeName, maybe in the future we could have (custom?) annotations such as @Node(name="myField")
- Have a configuration settings in hibernate.cfg.xml that indicates to serialize the XML using UNqualified classnames (or fully qualified) to have little more fancy/pretty XML.

I think this bugfix is quite important for a bunch of users that worked around this bug by using for example JibX:

http://forum.hibernate.org/viewtopic.php?t=947949
http://forum.hibernate.org/viewtopic.php?t=925621
http://forum.hibernate.org/viewtopic.php?t=959203
http://forum.hibernate.org/viewtopic.php?t=962051

"Note that this is an experimental feature in Hibernate 3.0 and is under extremely active development." (Chapter 18, reference doc)

Emmanuel, thanks for the directions. And...would you guys be a little more extreme on this XML feature?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 08, 2007 1:31 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
yes, this is on our radar for 3.3

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 08, 2007 1:33 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Thanks, I'll apply your patch. BTW I like @Node: if you have time, a patch would be great :-)

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 15, 2007 10:54 am 
Newbie

Joined: Wed Dec 01, 2004 12:27 pm
Posts: 11
Sorry for bumping this thread, I opened a JIRA issue at http://opensource.atlassian.com/project ... se/ANN-531 about the patch.

Is it intended that entity collections of a parent don't get their properties deserialized ?

thanks


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 15, 2007 11:32 am 
Newbie

Joined: Fri Jul 21, 2006 7:20 am
Posts: 15
Actually thats the difference between deep serialization or just serialization of the object. Personally I don't have problems with the items in the collection just having an ID and not the rest of the properties because I need an XML file for every object.

However I can imagine situations where you want to have one XML document that contains your whole object tree. I like the way XStream solves this by using xpaths in the XML to represent pointers to objects that were already (somewhere else) in the XML file.

Just an idea, but what about extending the dom4jentitytuplizer and creating your own way of serialization..?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.