Author: rmannibucau
Date: Wed Aug  3 12:58:30 2011
New Revision: 1153468

URL: http://svn.apache.org/viewvc?rev=1153468&view=rev
Log:
adding support for save/delete/update in QueryProxy

Modified:
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/QueryProxy.java
    
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/DynamicEJBImplTest.java
    
openejb/trunk/openejb3/examples/rest-on-ejb/src/main/java/org/superbiz/rest/User.java

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java?rev=1153468&r1=1153467&r2=1153468&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java
 Wed Aug  3 12:58:30 2011
@@ -1204,7 +1204,7 @@ public class BeanContext extends Deploym
         WebBeansContext webBeansContext = null;
         AbstractInjectionTargetBean<Object> beanDefinition = null;
         ConstructorInjectionBean<Object> beanConstructor = null;
-        if (!beanClass.equals(localInterface)) { // not a dynamic proxy 
implementation
+        if (!isDynamicallyImplemented()) { // not a dynamic proxy 
implementation
             webBeansContext = 
getModuleContext().getAppContext().getWebBeansContext();
 
             beanDefinition = get(CdiEjbBean.class);
@@ -1221,13 +1221,13 @@ public class BeanContext extends Deploym
             final Class beanClass = this.getBeanClass();
 
             CreationalContext<Object> creationalContext = 
get(CreationalContext.class);
-            if (webBeansContext != null && creationalContext == null) {
+            if (creationalContext == null && !isDynamicallyImplemented()) {
                 creationalContext = 
webBeansContext.getBeanManagerImpl().createCreationalContext(beanDefinition);
             }
 
             // Create bean instance
             final Object beanInstance;
-            if (beanConstructor != null) {
+            if (!isDynamicallyImplemented()) {
                 final InjectionProcessor injectionProcessor = new 
InjectionProcessor(beanConstructor.create(creationalContext), 
this.getInjections(), InjectionProcessor.unwrap(ctx));
 
                 beanInstance = injectionProcessor.createInstance();

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java?rev=1153468&r1=1153467&r2=1153468&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/ivm/EjbHomeProxyHandler.java
 Wed Aug  3 12:58:30 2011
@@ -132,9 +132,8 @@ public abstract class EjbHomeProxyHandle
             EjbObjectProxyHandler handler = 
newEjbObjectHandler(getBeanContext(), primaryKey, objectInterfaceType, 
this.getInterfaces(), mainInterface);
 
             // TODO Is it correct for ManagedBean injection via managed bean 
class?
-            if (getBeanContext().isDynamicallyImplemented()) { // dynamic 
proxy implementation
-                return DynamicProxyImplFactory.newProxy(getBeanContext());
-            } if (InterfaceType.LOCALBEAN.equals(objectInterfaceType) || 
getBeanContext().getComponentType().equals(BeanType.MANAGED)) {
+            if ((InterfaceType.LOCALBEAN.equals(objectInterfaceType) || 
getBeanContext().getComponentType().equals(BeanType.MANAGED))
+                    &&! getBeanContext().isDynamicallyImplemented()) {
                 return 
LocalBeanProxyFactory.newProxyInstance(handler.getBeanContext().getClassLoader(),
 handler.getBeanContext().getBeanClass(), handler);
             } else {
                 List<Class> proxyInterfaces = new 
ArrayList<Class>(handler.getInterfaces().size() + 1);

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/QueryProxy.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/QueryProxy.java?rev=1153468&r1=1153467&r2=1153468&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/QueryProxy.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/QueryProxy.java
 Wed Aug  3 12:58:30 2011
@@ -1,19 +1,24 @@
 package org.apache.openejb.util.proxy;
 
+import org.apache.commons.beanutils.BeanUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
 
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
+import javax.persistence.TypedQuery;
 import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Expression;
 import javax.persistence.criteria.Path;
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
+import javax.persistence.metamodel.Attribute;
 import javax.persistence.metamodel.EntityType;
 import javax.persistence.metamodel.SingularAttribute;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
@@ -21,6 +26,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -30,11 +36,14 @@ public class QueryProxy implements Invoc
     private static final Logger LOGGER = 
Logger.getInstance(LogCategory.OPENEJB, QueryProxy.class);
 
     // keywords
+    public static final String PERSIST_NAME = "save";
+    public static final String MERGE_NAME = "update";
+    public static final String REMOVE_NAME = "delete";
     public static final String FIND_PREFIX = "find";
     public static final String BY = "By";
     public static final String AND = "And";
 
-    // cache for current instance
+    // cache for finders of the current instance
     private final Map<String, Class<?>> RETURN_TYPES = new 
ConcurrentHashMap<String, Class<?>>();
     private final Map<String, List<String>> CONDITIONS = new 
ConcurrentHashMap<String, List<String>>();
 
@@ -49,24 +58,113 @@ public class QueryProxy implements Invoc
             return method.invoke(this, args);
         }
 
-        if (!method.getName().startsWith(FIND_PREFIX)) {
-            throw new IllegalArgumentException("finder should start with 
find");
+        final String methodName = method.getName();
+        final Class<?> returnType = method.getReturnType();
+
+        // simple cases
+        if (PERSIST_NAME.equals(methodName)) {
+            persist(args, returnType);
+            return null; // void
+        }
+
+        if (MERGE_NAME.equals(methodName)) {
+            return merge(args, returnType);
+        }
+
+        if (REMOVE_NAME.equals(methodName)) {
+            remove(args, returnType);
+            return null; // void
         }
 
+        // other cases (finders)
+        if (methodName.startsWith(FIND_PREFIX)) {
+            return find(method, args);
+        }
+
+        throw new IllegalArgumentException("method not yet managed");
+    }
+
+    private Object find(Method method, Object[] args) {
         final String methodName = method.getName();
+
         Class<?> type;
         if (RETURN_TYPES.containsKey(methodName)) {
             type = RETURN_TYPES.get(methodName);
         } else {
             type =  getGenericType(method.getGenericReturnType());
+            RETURN_TYPES.put(methodName, type);
         }
-        Query query = getQuery(em, methodName, type, args);
+
+        Query query = createFinderQuery(em, methodName, type, args);
+
         if (Collection.class.isAssignableFrom(method.getReturnType())) {
             return query.getResultList();
         }
         return query.getSingleResult();
     }
 
+    private void remove(Object[] args, Class<?> returnType) {
+        if (args != null && args.length == 1 && returnType.equals(Void.TYPE)) {
+            Object entity = args[0];
+            if (!em.contains(entity)) { // should not be done (that's why it 
is not cached) but can be easier...
+                final Class<?> entityClass = entity.getClass();
+                final EntityType<? extends Object> et = 
em.getMetamodel().entity(entity.getClass());
+
+                if (!et.hasSingleIdAttribute()) {
+                    throw new IllegalArgumentException("Dynamic EJB doesn't 
manage IdClass yet");
+                }
+
+                SingularAttribute<?, ?> id = null; // = et.getId(entityClass); 
doesn't work with openJPA
+                for (SingularAttribute<?, ?> sa : et.getSingularAttributes()) {
+                    if (sa.isId()) {
+                        id = sa;
+                        break;
+                    }
+                }
+                if (id == null) {
+                    throw new IllegalArgumentException("id field not found");
+                }
+                final String idName = id.getName();
+
+                Object idValue;
+                try {
+                    idValue = BeanUtils.getProperty(entity, idName);;
+                } catch (InvocationTargetException e) {
+                    throw new IllegalArgumentException("can't invoke to get 
entity id");
+                } catch (NoSuchMethodException e) {
+                    throw new IllegalArgumentException("can't find the method 
to get entity id");
+                } catch (IllegalAccessException e) {
+                    throw new IllegalArgumentException("can't access 
field/method to get entity id");
+                }
+
+                entity = em.find(et.getJavaType(), idValue);
+                if (entity == null) {
+                    throw new IllegalArgumentException("entity " + entity + " 
is not managed and can't be found.");
+                }
+            }
+            em.remove(entity);
+        } else {
+            throw new IllegalArgumentException(REMOVE_NAME + " should have 
only one parameter and return void");
+        }
+    }
+
+    private Object merge(Object[] args, Class<?> returnType) {
+        if (args != null && args.length == 1 && 
returnType.equals(args[0].getClass())) {
+            return em.merge(args[0]);
+        } else {
+            throw new IllegalArgumentException(MERGE_NAME + " should have only 
one parameter and return the same" +
+                    " type than the parameter type");
+        }
+    }
+
+    private void persist(Object[] args, Class<?> returnType) {
+        if (args != null && args.length == 1 && returnType.equals(Void.TYPE)) {
+            em.persist(args[0]);
+        } else {
+            throw new IllegalArgumentException(PERSIST_NAME + " should have 
only one parameter and return void");
+        }
+    }
+
     private Class<?> getGenericType(Type type) {
         if (type instanceof ParameterizedType) {
             ParameterizedType pt = (ParameterizedType) type;
@@ -74,11 +172,12 @@ public class QueryProxy implements Invoc
                 return (Class<?>) pt.getActualTypeArguments()[0];
             }
         }
-        return (Class<?>) type;
+        return Class.class.cast(type);
     }
 
-    private <T> Query getQuery(EntityManager entityManager, String methodName, 
Class<T> entityType, Object[] args) {
+    private <T> Query createFinderQuery(EntityManager entityManager, String 
methodName, Class<T> entityType, Object[] args) {
         final List<String> conditions = parseMethodName(methodName);
+
         final EntityType<T> et = 
entityManager.getMetamodel().entity(entityType);
         final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
 
@@ -114,7 +213,22 @@ public class QueryProxy implements Invoc
             query = query.where(where);
         }
 
-        return entityManager.createQuery(query);
+        // pagination
+        TypedQuery<?> emQuery = entityManager.createQuery(query);
+        if (args != null && args.length == conditions.size() + 2
+                && isInt(args[args.length - 2].getClass()) && 
isInt(args[args.length - 1].getClass())) {
+            int first = (Integer) args[args.length - 2];
+            int max = (Integer) args[args.length - 1];
+
+            emQuery.setFirstResult(first);
+            emQuery.setMaxResults(max);
+        }
+
+        return emQuery;
+    }
+
+    private boolean isInt(Class<?> aClass) {
+        return Integer.TYPE.equals(aClass) || Integer.class.equals(aClass);
     }
 
     private List<String> parseMethodName(final String methodName) {

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/DynamicEJBImplTest.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/DynamicEJBImplTest.java?rev=1153468&r1=1153467&r2=1153468&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/DynamicEJBImplTest.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/DynamicEJBImplTest.java
 Wed Aug  3 12:58:30 2011
@@ -25,23 +25,29 @@ import org.apache.openejb.jee.jpa.unit.P
 import org.apache.openejb.junit.ApplicationComposer;
 import org.apache.openejb.junit.Configuration;
 import org.apache.openejb.junit.Module;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import javax.ejb.EJB;
+import javax.ejb.EJBException;
 import javax.ejb.Singleton;
 import javax.ejb.Stateless;
 import javax.persistence.Entity;
 import javax.persistence.EntityManager;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
+import javax.persistence.NoResultException;
 import javax.persistence.PersistenceContext;
 import java.util.Collection;
 import java.util.Properties;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
 
 /**
  * @author rmannibucau
@@ -60,6 +66,11 @@ public class DynamicEJBImplTest {
         }
     }
 
+    @After public void checkAll() {
+        Collection<User> users = dao.findAll();
+        assertEquals(10, users.size());
+    }
+
     @Test public void simple() {
         User user = dao.findById(1);
         assertNotNull(user);
@@ -71,6 +82,49 @@ public class DynamicEJBImplTest {
         assertEquals(10, users.size());
     }
 
+    @Test public void pagination() {
+        Collection<User> users = dao.findAll(0, 5);
+        assertEquals(5, users.size());
+
+        users = dao.findAll(6, 1);
+        assertEquals(1, users.size());
+        assertEquals(7, users.iterator().next().getId());
+    }
+
+    @Test public void persist() {
+        User u = new User();
+        dao.save(u);
+        assertNotNull(u.getId());
+        util.remove(u);
+    }
+
+    @Test public void remove() {
+        User u = new User();
+        dao.save(u);
+        assertNotNull(u.getId());
+        dao.delete(u);
+        try {
+            dao.findById(u.getId());
+            fail();
+        } catch (EJBException ee) {
+            assertTrue(ee.getCause() instanceof NoResultException);
+        }
+    }
+
+    @Test public void merge() {
+        User u = new User();
+        u.setInfo("one");
+        dao.save(u);
+        assertEquals("one", u.getInfo());
+        assertNotNull(u.getId());
+
+        u.setInfo("another one");
+        dao.update(u);
+        assertEquals("another one", u.getInfo());
+
+        dao.delete(u);
+    }
+
     @Test public void oneCriteria() {
         Collection<User> users = dao.findByName("foo");
         assertEquals(4, users.size());
@@ -102,6 +156,13 @@ public class DynamicEJBImplTest {
         Collection<User> findByNameAndInfo(String name, String info);
 
         Collection<User> findAll();
+        Collection<User> findAll(int first, int max);
+
+        void save(User u);
+
+        void delete(User u);
+
+        User update(User u);
     }
 
     @Entity public static class User {
@@ -168,6 +229,10 @@ public class DynamicEJBImplTest {
         public UserDAO getDao() {
             return dao;
         }
+
+        public void remove(User u) {
+            em.remove(em.find(u.getClass(), u.getId()));
+        }
     }
 
     @Configuration public Properties config() {

Modified: 
openejb/trunk/openejb3/examples/rest-on-ejb/src/main/java/org/superbiz/rest/User.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/examples/rest-on-ejb/src/main/java/org/superbiz/rest/User.java?rev=1153468&r1=1153467&r2=1153468&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/examples/rest-on-ejb/src/main/java/org/superbiz/rest/User.java
 (original)
+++ 
openejb/trunk/openejb3/examples/rest-on-ejb/src/main/java/org/superbiz/rest/User.java
 Wed Aug  3 12:58:30 2011
@@ -83,7 +83,7 @@ public class User implements Cloneable {
         if (this == o) {
             return true;
         }
-        if (o == null || getClass() != o.getClass()) {
+        if (o == null || !User.class.isAssignableFrom(o.getClass())) {
             return false;
         }
 


Reply via email to