You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by js...@apache.org on 2007/04/03 20:33:12 UTC
svn commit: r525236 - in /activemq/camel/trunk:
camel-core/src/main/java/org/apache/camel/impl/converter/
camel-core/src/main/java/org/apache/camel/util/
camel-jpa/src/main/java/org/apache/camel/component/jpa/
camel-jpa/src/test/java/org/apache/camel/c...
Author: jstrachan
Date: Tue Apr 3 11:33:10 2007
New Revision: 525236
URL: http://svn.apache.org/viewvc?view=rev&rev=525236
Log:
Added a test case showing how to use a named query with JPA along with using an annotation to mark the @Consumed method; so POJO developers can write a method to be invoked on a consume (to set a flag or update a step to the next state etc). Also performed a minor refactor to move more reusable code into the core module (for dealing with exception handling of reflection calls).
Added:
activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/Consumed.java (with props)
Modified:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodTypeConverter.java
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodTypeConverter.java
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java
activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaConsumer.java
activemq/camel/trunk/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaWithNamedQueryTest.java
activemq/camel/trunk/camel-jpa/src/test/java/org/apache/camel/examples/MultiSteps.java
Modified: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodTypeConverter.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodTypeConverter.java?view=diff&rev=525236&r1=525235&r2=525236
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodTypeConverter.java (original)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodTypeConverter.java Tue Apr 3 11:33:10 2007
@@ -19,6 +19,7 @@
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.TypeConverter;
+import org.apache.camel.util.ObjectHelper;
import org.apache.camel.impl.CachingInjector;
import java.lang.reflect.InvocationTargetException;
@@ -49,14 +50,6 @@
if (instance == null) {
throw new RuntimeCamelException("Could not instantiate aninstance of: " + type.getName());
}
- try {
- return (T) method.invoke(instance, value);
- }
- catch (IllegalAccessException e) {
- throw new RuntimeCamelException(e);
- }
- catch (InvocationTargetException e) {
- throw new RuntimeCamelException(e.getCause());
- }
+ return (T) ObjectHelper.invokeMethod(method, instance, value);
}
}
Modified: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodTypeConverter.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodTypeConverter.java?view=diff&rev=525236&r1=525235&r2=525236
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodTypeConverter.java (original)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodTypeConverter.java Tue Apr 3 11:33:10 2007
@@ -19,6 +19,7 @@
import org.apache.camel.TypeConverter;
import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.util.ObjectHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -43,14 +44,6 @@
}
public <T> T convertTo(Class<T> type, Object value) {
- try {
- return (T) method.invoke(null, value);
- }
- catch (IllegalAccessException e) {
- throw new RuntimeCamelException(e);
- }
- catch (InvocationTargetException e) {
- throw new RuntimeCamelException(e.getCause());
- }
+ return (T) ObjectHelper.invokeMethod(method, null, value);
}
}
Modified: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java?view=diff&rev=525236&r1=525235&r2=525236
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java (original)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java Tue Apr 3 11:33:10 2007
@@ -16,12 +16,18 @@
*/
package org.apache.camel.util;
+import org.apache.camel.RuntimeCamelException;
import org.apache.camel.converter.ObjectConverter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
/**
* @version $Revision$
@@ -67,27 +73,26 @@
}
}
-
public static void notNull(Object value, String name) {
if (value == null) {
throw new NullPointerException("No " + name + " specified");
}
}
-
+
public static String[] splitOnCharacter(String value, String needle, int count) {
- String rc [] = new String[count];
- rc[0] = value;
- for ( int i=1; i < count; i++ ) {
- String v = rc[i-1];
- int p = v.indexOf(needle);
- if( p < 0 ) {
- return rc;
- }
- rc[i-1] = v.substring(0,p);
- rc[i] = v.substring(p+1);
- }
- return rc;
- }
+ String rc[] = new String[count];
+ rc[0] = value;
+ for (int i = 1; i < count; i++) {
+ String v = rc[i - 1];
+ int p = v.indexOf(needle);
+ if (p < 0) {
+ return rc;
+ }
+ rc[i - 1] = v.substring(0, p);
+ rc[i] = v.substring(p + 1);
+ }
+ return rc;
+ }
/**
* Returns true if the collection contains the specified value
@@ -115,7 +120,7 @@
/**
* A helper method to access a system property, catching any security exceptions
*
- * @param name the name of the system property required
+ * @param name the name of the system property required
* @param defaultValue the default value to use if the property is not available or a security exception prevents access
* @return the system property value or the default value if the property is not available or security does not allow its access
*/
@@ -148,11 +153,11 @@
public static Class<?> loadClass(String name) {
return loadClass(name, ObjectHelper.class.getClassLoader());
}
-
+
/**
* Attempts to load the given class name using the thread context class loader or the given class loader
*
- * @param name the name of the class to load
+ * @param name the name of the class to load
* @param loader the class loader to use after the thread context class loader
* @return the class or null if it could not be loaded
*/
@@ -172,5 +177,48 @@
}
}
return null;
+ }
+
+ /**
+ * A helper method to invoke a method via reflection and wrap any exceptions
+ * as {@link RuntimeCamelException} instances
+ *
+ * @param method the method to invoke
+ * @param instance the object instance (or null for static methods)
+ * @param parameters the parameters to the method
+ * @return the result of the method invocation
+ */
+ public static Object invokeMethod(Method method, Object instance, Object... parameters) {
+ try {
+ return method.invoke(instance, parameters);
+ }
+ catch (IllegalAccessException e) {
+ throw new RuntimeCamelException(e);
+ }
+ catch (InvocationTargetException e) {
+ throw new RuntimeCamelException(e.getCause());
+ }
+ }
+
+ /**
+ * Returns a list of methods which are annotated with the given annotation
+ *
+ * @param type the type to reflect on
+ * @param annotationType the annotation type
+ * @return a list of the methods found
+ */
+ public static List<Method> findMethodsWithAnnotation(Class<?> type, Class<? extends Annotation> annotationType) {
+ List<Method> answer = new ArrayList<Method>();
+ do {
+ Method[] methods = type.getDeclaredMethods();
+ for (Method method : methods) {
+ if (method.getAnnotation(annotationType) != null) {
+ answer.add(method);
+ }
+ }
+ type = type.getSuperclass();
+ }
+ while (type != null);
+ return answer;
}
}
Added: activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/Consumed.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/Consumed.java?view=auto&rev=525236
==============================================================================
--- activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/Consumed.java (added)
+++ activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/Consumed.java Tue Apr 3 11:33:10 2007
@@ -0,0 +1,19 @@
+package org.apache.camel.component.jpa;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * An annotation to mark a method to be invoked when an entity bean has been succesfully processed
+ * by a Camel consumer, so that it can be updated in some way to remove it from the query set.
+ *
+ * For example a method may be marked to set an active flag to false or to update some status value to the next step in a workflow
+ *
+ * @version $Revision$
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface Consumed {
+}
Propchange: activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/Consumed.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/Consumed.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/Consumed.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaConsumer.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaConsumer.java?view=diff&rev=525236&r1=525235&r2=525236
==============================================================================
--- activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaConsumer.java (original)
+++ activemq/camel/trunk/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaConsumer.java Tue Apr 3 11:33:10 2007
@@ -20,6 +20,7 @@
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.impl.PollingConsumer;
+import org.apache.camel.util.ObjectHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.jpa.JpaCallback;
@@ -28,6 +29,7 @@
import javax.persistence.LockModeType;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
+import java.lang.reflect.Method;
import java.util.List;
/**
@@ -67,6 +69,7 @@
getDeleteHandler().deleteObject(entityManager, result);
}
}
+ entityManager.flush();
return null;
}
});
@@ -176,7 +179,22 @@
protected DeleteHandler<Object> createDeleteHandler() {
// TODO auto-discover an annotation in the entity bean to indicate the process completed method call?
-
+ Class<?> entityType = getEndpoint().getEntityType();
+ if (entityType != null) {
+ List<Method> methods = ObjectHelper.findMethodsWithAnnotation(entityType, Consumed.class);
+ if (methods.size() > 1) {
+ throw new IllegalArgumentException("Only one method can be annotated with the @Consumed annotation but found: " + methods);
+ }
+ else if (methods.size() == 1) {
+ final Method method = methods.get(0);
+
+ return new DeleteHandler<Object>() {
+ public void deleteObject(EntityManager entityManager, Object entityBean) {
+ ObjectHelper.invokeMethod(method, entityBean);
+ }
+ };
+ }
+ }
return new DeleteHandler<Object>() {
public void deleteObject(EntityManager entityManager, Object entityBean) {
entityManager.remove(entityBean);
Modified: activemq/camel/trunk/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaWithNamedQueryTest.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaWithNamedQueryTest.java?view=diff&rev=525236&r1=525235&r2=525236
==============================================================================
--- activemq/camel/trunk/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaWithNamedQueryTest.java (original)
+++ activemq/camel/trunk/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaWithNamedQueryTest.java Tue Apr 3 11:33:10 2007
@@ -18,26 +18,25 @@
package org.apache.camel.component.jpa;
import junit.framework.TestCase;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.apache.camel.CamelContext;
-import org.apache.camel.Exchange;
import org.apache.camel.Consumer;
-import org.apache.camel.Processor;
import org.apache.camel.Endpoint;
-import org.apache.camel.examples.SendEmail;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
import org.apache.camel.examples.MultiSteps;
+import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.util.CamelClient;
import org.apache.camel.util.ServiceHelper;
-import org.apache.camel.impl.DefaultCamelContext;
-import org.springframework.orm.jpa.JpaTemplate;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.orm.jpa.JpaCallback;
+import org.springframework.orm.jpa.JpaTemplate;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
+import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import java.util.List;
/**
* @version $Revision$
@@ -101,6 +100,36 @@
MultiSteps result = receivedExchange.getIn().getBody(MultiSteps.class);
assertNotNull("Received a POJO", result);
assertEquals("address property", "foo@bar.com", result.getAddress());
+
+
+ // lets now test that the database is updated
+ // TODO we need to sleep as we will be invoked from inside the transaction!
+ Thread.sleep(1000);
+
+ transactionStrategy.execute(new JpaCallback() {
+ public Object doInJpa(EntityManager entityManager) throws PersistenceException {
+
+ // now lets assert that there are still 2 entities left
+ List<MultiSteps> rows = entityManager.createQuery("select x from MultiSteps x").getResultList();
+ assertEquals("Number of entities: " + rows, 2, rows.size());
+
+ int counter = 1;
+ for (MultiSteps row : rows) {
+ log.info("entity: " + counter++ + " = " + row);
+
+ if (row.getAddress().equals("foo@bar.com")) {
+ log.info("Found updated row: " + row);
+
+ assertEquals("Updated row step for: " + row, 2, row.getStep());
+ }
+ else {
+ // dummy row
+ assertEquals("dummy row step for: " + row, 4, row.getStep());
+ }
+ }
+ return null;
+ }
+ });
}
@Override
Modified: activemq/camel/trunk/camel-jpa/src/test/java/org/apache/camel/examples/MultiSteps.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-jpa/src/test/java/org/apache/camel/examples/MultiSteps.java?view=diff&rev=525236&r1=525235&r2=525236
==============================================================================
--- activemq/camel/trunk/camel-jpa/src/test/java/org/apache/camel/examples/MultiSteps.java (original)
+++ activemq/camel/trunk/camel-jpa/src/test/java/org/apache/camel/examples/MultiSteps.java Tue Apr 3 11:33:10 2007
@@ -17,6 +17,10 @@
*/
package org.apache.camel.examples;
+import org.apache.camel.component.jpa.Consumed;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
@@ -24,12 +28,16 @@
/**
* Represents a task which has multiple steps so that it can move from stage to stage
+ * with the method annotated with {@link @Consumed} being invoked when the Camel consumer
+ * has processed the entity bean
*
* @version $Revision$
*/
@Entity
@NamedQuery(name = "step1", query="select x from MultiSteps x where x.step = 1")
public class MultiSteps {
+ private static final transient Log log = LogFactory.getLog(MultiSteps.class);
+
private Long id;
private String address;
private int step;
@@ -71,5 +79,15 @@
public void setStep(int step) {
this.step = step;
+ }
+
+ /**
+ * This method is invoked after the entity bean is processed successfully by a Camel endpoint
+ */
+ @Consumed
+ public void goToNextStep() {
+ setStep(getStep() + 1);
+
+ log.info("Invoked the completion complete method. Now updated the step to: " + getStep());
}
}