You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by da...@apache.org on 2008/03/08 16:23:23 UTC

svn commit: r634989 - in /tapestry/tapestry5/trunk/tapestry-hibernate/src: main/java/org/apache/tapestry/hibernate/ main/java/org/apache/tapestry/internal/hibernate/ site/ site/apt/ test/java/org/apache/tapestry/hibernate/integration/ test/java/org/exa...

Author: dadams
Date: Sat Mar  8 07:23:21 2008
New Revision: 634989

URL: http://svn.apache.org/viewvc?rev=634989&view=rev
Log:
TAPESTRY-1653: Provide automatic ValueEncoders for Hibernate entities

Added:
    tapestry/tapestry5/trunk/tapestry-hibernate/src/main/java/org/apache/tapestry/internal/hibernate/HibernateEntityValueEncoder.java
    tapestry/tapestry5/trunk/tapestry-hibernate/src/site/apt/userguide.apt
    tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/pages/EncodeEntities.java
    tapestry/tapestry5/trunk/tapestry-hibernate/src/test/webapp/EncodeEntities.tml
Modified:
    tapestry/tapestry5/trunk/tapestry-hibernate/src/main/java/org/apache/tapestry/hibernate/HibernateModule.java
    tapestry/tapestry5/trunk/tapestry-hibernate/src/site/site.xml
    tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/apache/tapestry/hibernate/integration/TapestryHibernateIntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/entities/User.java
    tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/pages/Start.java
    tapestry/tapestry5/trunk/tapestry-hibernate/src/test/resources/hibernate.cfg.xml
    tapestry/tapestry5/trunk/tapestry-hibernate/src/test/webapp/Start.tml

Modified: tapestry/tapestry5/trunk/tapestry-hibernate/src/main/java/org/apache/tapestry/hibernate/HibernateModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate/src/main/java/org/apache/tapestry/hibernate/HibernateModule.java?rev=634989&r1=634988&r2=634989&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate/src/main/java/org/apache/tapestry/hibernate/HibernateModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-hibernate/src/main/java/org/apache/tapestry/hibernate/HibernateModule.java Sat Mar  8 07:23:21 2008
@@ -14,12 +14,17 @@
 
 package org.apache.tapestry.hibernate;
 
+import org.apache.tapestry.ValueEncoder;
 import org.apache.tapestry.internal.InternalConstants;
 import org.apache.tapestry.internal.hibernate.DefaultHibernateConfigurer;
+import org.apache.tapestry.internal.hibernate.HibernateEntityValueEncoder;
 import org.apache.tapestry.internal.hibernate.HibernateSessionManagerImpl;
 import org.apache.tapestry.internal.hibernate.HibernateSessionSourceImpl;
 import org.apache.tapestry.internal.hibernate.PackageNameHibernateConfigurer;
 import org.apache.tapestry.ioc.Configuration;
+import org.apache.tapestry.ioc.MappedConfiguration;
+import org.apache.tapestry.ioc.ObjectLocator;
+
 import static org.apache.tapestry.ioc.IOCConstants.PERTHREAD_SCOPE;
 import org.apache.tapestry.ioc.OrderedConfiguration;
 import org.apache.tapestry.ioc.annotations.Inject;
@@ -30,11 +35,15 @@
 import org.apache.tapestry.ioc.services.PerthreadManager;
 import org.apache.tapestry.ioc.services.PropertyShadowBuilder;
 import org.apache.tapestry.ioc.services.RegistryShutdownHub;
+import org.apache.tapestry.ioc.services.TypeCoercer;
 import org.apache.tapestry.services.AliasContribution;
+import org.apache.tapestry.services.ValueEncoderFactory;
 import org.hibernate.Session;
+import org.hibernate.mapping.PersistentClass;
 import org.slf4j.Logger;
 
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
 
 public class HibernateModule
@@ -129,4 +138,30 @@
         config.add("PackageName", new PackageNameHibernateConfigurer(packageManager, classNameLocator));
     }
 
+    /**
+     * Contributes {@link ValueEncoderFactory}s for all registered Hibernate entity classes. Encoding and decoding are based
+     * on the id property value of the entity using type coercion. Hence, if the id can be coerced to a String and back then
+     * the entity can be coerced.
+     */
+    @SuppressWarnings("unchecked")
+    public static void contributeValueEncoderSource(MappedConfiguration<Class, ValueEncoderFactory> configuration,
+                                                    final HibernateSessionSource sessionSource,
+                                                    final Session session,
+                                                    final TypeCoercer typeCoercer)
+    {
+    	org.hibernate.cfg.Configuration config = sessionSource.getConfiguration();
+    	Iterator<PersistentClass> mappings = config.getClassMappings();
+    	while(mappings.hasNext()) {
+    		final PersistentClass persistentClass = mappings.next();
+    		final Class entityClass = persistentClass.getMappedClass();
+			
+			ValueEncoderFactory factory = new ValueEncoderFactory() {
+				public ValueEncoder create(Class type) {
+					return new HibernateEntityValueEncoder(entityClass, persistentClass, session, typeCoercer);
+				}
+			};
+			
+			configuration.add(entityClass, factory);
+    	}
+    }
 }

Added: tapestry/tapestry5/trunk/tapestry-hibernate/src/main/java/org/apache/tapestry/internal/hibernate/HibernateEntityValueEncoder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate/src/main/java/org/apache/tapestry/internal/hibernate/HibernateEntityValueEncoder.java?rev=634989&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate/src/main/java/org/apache/tapestry/internal/hibernate/HibernateEntityValueEncoder.java (added)
+++ tapestry/tapestry5/trunk/tapestry-hibernate/src/main/java/org/apache/tapestry/internal/hibernate/HibernateEntityValueEncoder.java Sat Mar  8 07:23:21 2008
@@ -0,0 +1,59 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.hibernate;
+
+import java.io.Serializable;
+
+import org.apache.tapestry.ValueEncoder;
+import org.apache.tapestry.ioc.internal.util.Defense;
+import org.apache.tapestry.ioc.services.TypeCoercer;
+import org.hibernate.Session;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Property;
+import org.hibernate.property.Getter;
+
+public final class HibernateEntityValueEncoder<E> implements ValueEncoder<E> {
+	private final Class<E> _entityClass;
+	private final PersistentClass _persistentClass;
+	private final Session _session;
+	private final TypeCoercer _typeCoercer;
+	private final Getter _idGetter;
+	
+	public HibernateEntityValueEncoder(Class<E> entityClass, PersistentClass persistentClass, Session session, TypeCoercer typeCoercer) {
+		super();
+		_entityClass = entityClass;
+		_persistentClass = persistentClass;
+		_session = session;
+		_typeCoercer = typeCoercer;
+		
+		Property property = _persistentClass.getIdentifierProperty();
+		_idGetter = property.getPropertyAccessor(_entityClass).getGetter(_entityClass, property.getName());
+	}
+		
+	public String toClient(E value) {
+		Object id = _idGetter.get(value);
+		return _typeCoercer.coerce(id, String.class);
+	}
+
+	@SuppressWarnings("unchecked")
+	public E toValue(String clientValue) {
+		Class<?> idType = _idGetter.getReturnType();
+		
+		Object id = _typeCoercer.coerce(clientValue, idType);
+		Serializable ser = Defense.cast(id, Serializable.class, "id");
+		return (E)_session.get(_entityClass, ser);
+	}
+	
+}

Added: tapestry/tapestry5/trunk/tapestry-hibernate/src/site/apt/userguide.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate/src/site/apt/userguide.apt?rev=634989&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate/src/site/apt/userguide.apt (added)
+++ tapestry/tapestry5/trunk/tapestry-hibernate/src/site/apt/userguide.apt Sat Mar  8 07:23:21 2008
@@ -0,0 +1,31 @@
+  ----
+  User Guide
+  ----
+  
+Entity value encoding
+
+  Value encoders are automatically created for all mapped Hibernate entity types. This is done by encoding the entity as it's 
+  id (coerced to a String) and decoding the entity by looking it up in the Hibernate Session using the encoded id. Consider
+  the following:
+  
++----+
+public class ViewPerson {
+  @Property
+  private Person _person;
+  
+  void onActivate(Person person)
+  {
+    _person = person;
+  }
+}
++----+   
+
++----+
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+<body>
+  The person's name is: ${person.name}
+</body>
+</html>
++----+
+
+  Accessing the page as <</viewperson/152>> would load the Person entity with id 152 and use that as the page context.

Modified: tapestry/tapestry5/trunk/tapestry-hibernate/src/site/site.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate/src/site/site.xml?rev=634989&r1=634988&r2=634989&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate/src/site/site.xml (original)
+++ tapestry/tapestry5/trunk/tapestry-hibernate/src/site/site.xml Sat Mar  8 07:23:21 2008
@@ -40,6 +40,7 @@
     <menu name="Quick Links">
       <item name="About" href="index.html"/>
       <item name="Configuration" href="conf.html"/>
+      <item name="User guide" href="userguide.html" />
       <item name="Download" href="http://tapestry.apache.org/download.html"/>
     </menu>
         

Modified: tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/apache/tapestry/hibernate/integration/TapestryHibernateIntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/apache/tapestry/hibernate/integration/TapestryHibernateIntegrationTests.java?rev=634989&r1=634988&r2=634989&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/apache/tapestry/hibernate/integration/TapestryHibernateIntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/apache/tapestry/hibernate/integration/TapestryHibernateIntegrationTests.java Sat Mar  8 07:23:21 2008
@@ -25,12 +25,18 @@
         super("src/test/webapp");
     }
 
-    /** Only needed until actual integration tests are put in. Just proves the integration
-     * tests are set up correctly.
-     */
-    public void test_placeholder() throws Exception {
-		open("/");
-		// just make sure we can get the hibernate Session
-		assertTrue(getText("//span[@id='session']").length() > 0);
+	public void test_valueencode_all_entity_types() throws Exception {
+		open("/encodeentities");
+		
+		assertEquals(0, getText("//span[@id='name']").length());
+
+		// need to create an entity in order to link with one
+		clickAndWait("//a[@id='createentity']");
+		assertEquals("name", getText("//span[@id='name']"));
+		
+		// should return null for missing objects
+		open("/encodeentities/9999");
+		assertEquals(0, getText("//span[@id='name']").length());
 	}
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/entities/User.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/entities/User.java?rev=634989&r1=634988&r2=634989&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/entities/User.java (original)
+++ tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/entities/User.java Sat Mar  8 07:23:21 2008
@@ -22,67 +22,68 @@
 @Entity
 public class User
 {
+	// NOTE: Hibernate doesn't understand the '_' syntax. It will end up putting underscores on all the properties
     @Id @GeneratedValue
-    private Long _id;
+    private Long id;
 
-    private String _firstName;
+    private String firstName;
 
-    private String _lastName;
+    private String lastName;
 
-    private String _email;
+    private String email;
 
-    private String _encodedPassword;
+    private String encodedPassword;
 
     @Version
-    private int _version;
+    private int version;
 
     public String getEmail()
     {
-        return _email;
+        return email;
     }
 
     public String getEncodedPassword()
     {
-        return _encodedPassword;
+        return encodedPassword;
     }
 
     public String getFirstName()
     {
-        return _firstName;
+        return firstName;
     }
 
     public Long getId()
     {
-        return _id;
+        return id;
     }
 
     public String getLastName()
     {
-        return _lastName;
+        return lastName;
     }
 
     public int getVersion()
     {
-        return _version;
+        return version;
     }
 
     public void setEmail(String email)
     {
-        _email = email;
+        this.email = email;
     }
 
     public void setEncodedPassword(String encodedPassword)
     {
-        _encodedPassword = encodedPassword;
+        this.encodedPassword = encodedPassword;
     }
 
     public void setFirstName(String firstName)
     {
-        _firstName = firstName;
+        this.firstName = firstName;
     }
 
     public void setLastName(String lastName)
     {
-        _lastName = lastName;
+        this.lastName = lastName;
     }
 }

Added: tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/pages/EncodeEntities.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/pages/EncodeEntities.java?rev=634989&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/pages/EncodeEntities.java (added)
+++ tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/pages/EncodeEntities.java Sat Mar  8 07:23:21 2008
@@ -0,0 +1,37 @@
+package org.example.app0.pages;
+
+import java.util.List;
+
+import org.apache.tapestry.annotations.Property;
+import org.apache.tapestry.ioc.annotations.Inject;
+import org.example.app0.entities.User;
+import org.hibernate.Session;
+
+public class EncodeEntities {
+	@Inject
+	@Property
+	private Session _session;
+	
+	@SuppressWarnings("unused")
+	@Property
+	private User _user;
+	
+	void onCreate() {
+		User user = new User();
+		user.setFirstName("name");
+		_session.save(user);
+	}
+
+	@SuppressWarnings("unchecked")
+	User onPassivate() {
+		List<User> users = _session.createQuery("from User").list();
+		if (users.isEmpty())
+			return null;
+		
+		return users.get(0);
+	}
+	
+	void onActivate(User user) {
+		_user = user;
+	}
+}

Modified: tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/pages/Start.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/pages/Start.java?rev=634989&r1=634988&r2=634989&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/pages/Start.java (original)
+++ tapestry/tapestry5/trunk/tapestry-hibernate/src/test/java/org/example/app0/pages/Start.java Sat Mar  8 07:23:21 2008
@@ -14,13 +14,6 @@
 
 package org.example.app0.pages;
 
-import org.apache.tapestry.annotations.Property;
-import org.apache.tapestry.ioc.annotations.Inject;
-import org.hibernate.Session;
-
 public class Start {
-	@Property
-	@Inject
-	private Session _session;
 	
 }

Modified: tapestry/tapestry5/trunk/tapestry-hibernate/src/test/resources/hibernate.cfg.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate/src/test/resources/hibernate.cfg.xml?rev=634989&r1=634988&r2=634989&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate/src/test/resources/hibernate.cfg.xml (original)
+++ tapestry/tapestry5/trunk/tapestry-hibernate/src/test/resources/hibernate.cfg.xml Sat Mar  8 07:23:21 2008
@@ -23,20 +23,19 @@
 
   <session-factory>
     <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
-    <property name="hibernate.connection.url">jdbc:hsqldb:file:target/unit-testdb</property>
+    <property name="hibernate.connection.url">jdbc:hsqldb:mem:test</property>
     <property name="hibernate.connection.username">sa</property>
     <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
     
     <property name="show_sql">true</property>
     <property name="format_sql">true</property>
-    <property name="hbm2ddl.auto">create-drop</property>    
-    
+    <property name="hbm2ddl.auto">update</property>
+
     <property name="hibernate.c3p0.min_size">5</property>
     <property name="hibernate.c3p0.max_size">20</property>
     <property name="hibernate.c3p0.timeout">300</property>
     <property name="hibernate.c3p0.max_statements">50</property>
     <property name="hibernate.c3p0.idle_test_period">3000</property>
-    
   </session-factory>
 
 

Added: tapestry/tapestry5/trunk/tapestry-hibernate/src/test/webapp/EncodeEntities.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate/src/test/webapp/EncodeEntities.tml?rev=634989&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate/src/test/webapp/EncodeEntities.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-hibernate/src/test/webapp/EncodeEntities.tml Sat Mar  8 07:23:21 2008
@@ -0,0 +1,6 @@
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+<body>
+	<p>entity name: <span id="name"><t:if test="user">${user.firstName}</t:if></span></p>
+	<p>create entity: <t:eventlink event="create" t:id="createentity">create an entity</t:eventlink></p>
+</body>
+</html>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-hibernate/src/test/webapp/Start.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-hibernate/src/test/webapp/Start.tml?rev=634989&r1=634988&r2=634989&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-hibernate/src/test/webapp/Start.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-hibernate/src/test/webapp/Start.tml Sat Mar  8 07:23:21 2008
@@ -4,6 +4,5 @@
   </head>
   <body>
     <h2>Test application for tapestry-hibernate integration tests</h2>
-    The Hibernate session: <span id="session">${session}</span>
   </body>
 </html>