tomee-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rmannibu...@apache.org
Subject [13/50] tomee git commit: TOMEE-1951 making JPA CDI aware
Date Sat, 03 Dec 2016 16:37:39 GMT
TOMEE-1951 making JPA CDI aware


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/0737513a
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/0737513a
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/0737513a

Branch: refs/heads/tomee-1.7.x
Commit: 0737513ae6e4755ac94699b3b8b09ee2371ece09
Parents: 6379200
Author: rmannibucau <rmannibucau@apache.org>
Authored: Mon Oct 3 11:02:59 2016 +0200
Committer: rmannibucau <rmannibucau@apache.org>
Committed: Mon Oct 3 11:02:59 2016 +0200

----------------------------------------------------------------------
 .../openejb/assembler/classic/Assembler.java    |   6 +-
 .../classic/EntityManagerFactoryCallable.java   |  53 +++++++-
 .../assembler/classic/PersistenceBuilder.java   |   9 +-
 .../classic/ReloadableEntityManagerFactory.java |  47 ++++---
 .../openejb/persistence/JtaEntityManager.java   |   9 +-
 .../openejb/jpa/JPAHasBeanManagerTest.java      | 121 +++++++++++++++++++
 6 files changed, 216 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/0737513a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
index ae52f14..08eb1a3 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
@@ -765,6 +765,8 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
             final Map<String, Object> appBindings = appBuilder.buildBindings(JndiEncBuilder.JndiScope.app);
             final Context appJndiContext = appBuilder.build(appBindings);
 
+            final boolean cdiActive = shouldStartCdi(appInfo);
+
             try {
                 // Generate the cmp2/cmp1 concrete subclasses
                 final CmpJarBuilder cmpJarBuilder = new CmpJarBuilder(appInfo, classLoader);
@@ -861,7 +863,7 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
                 for (final PersistenceUnitInfo info : appInfo.persistenceUnits) {
                     final ReloadableEntityManagerFactory factory;
                     try {
-                        factory = persistenceBuilder.createEntityManagerFactory(info, classLoader,
validatorFactoriesByConfig);
+                        factory = persistenceBuilder.createEntityManagerFactory(info, classLoader,
validatorFactoriesByConfig, cdiActive);
                         containerSystem.getJNDIContext().bind(PERSISTENCE_UNIT_NAMING_CONTEXT
+ info.id, factory);
                         units.put(info.name, PERSISTENCE_UNIT_NAMING_CONTEXT + info.id);
                     } catch (final NameAlreadyBoundException e) {
@@ -907,7 +909,7 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
                     propagateApplicationExceptions(appInfo, classLoader, allDeployments);
                 }
 
-                if (shouldStartCdi(appInfo)) {
+                if (cdiActive) {
                     new CdiBuilder().build(appInfo, appContext, allDeployments);
                     ensureWebBeansContext(appContext);
                     appJndiContext.bind("app/BeanManager", appContext.getBeanManager());

http://git-wip-us.apache.org/repos/asf/tomee/blob/0737513a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java
index cb5706b..854c9c4 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java
@@ -19,11 +19,20 @@ package org.apache.openejb.assembler.classic;
 
 import org.apache.openejb.loader.SystemInstance;
 import org.apache.openejb.persistence.PersistenceUnitInfoImpl;
+import org.apache.openejb.util.LogCategory;
+import org.apache.openejb.util.Logger;
+import org.apache.webbeans.config.WebBeansContext;
+import org.apache.webbeans.container.InjectableBeanManager;
 
+import javax.enterprise.inject.spi.BeanManager;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.ValidationMode;
 import javax.persistence.spi.PersistenceProvider;
 import javax.validation.ValidatorFactory;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.Callable;
@@ -35,14 +44,29 @@ public class EntityManagerFactoryCallable implements Callable<EntityManagerFacto
     private final String persistenceProviderClassName;
     private final PersistenceUnitInfoImpl unitInfo;
     private final Map<ComparableValidationConfig, ValidatorFactory> potentialValidators;
+    private final boolean cdi;
     private ClassLoader appClassLoader;
 
     public EntityManagerFactoryCallable(final String persistenceProviderClassName, final
PersistenceUnitInfoImpl unitInfo,
-                                        final ClassLoader cl, final Map<ComparableValidationConfig,
ValidatorFactory> validators) {
+                                        final ClassLoader cl, final Map<ComparableValidationConfig,
ValidatorFactory> validators,
+                                        final boolean hasCdi) {
         this.persistenceProviderClassName = persistenceProviderClassName;
         this.unitInfo = unitInfo;
         this.appClassLoader = cl;
         this.potentialValidators = validators;
+        this.cdi = hasCdi;
+    }
+
+    public Class<?> getProvider() {
+        final ClassLoader old = Thread.currentThread().getContextClassLoader();
+        Thread.currentThread().setContextClassLoader(appClassLoader);
+        try {
+            return appClassLoader.loadClass(persistenceProviderClassName);
+        } catch (final ClassNotFoundException e) {
+            throw new IllegalArgumentException(e);
+        } finally {
+            Thread.currentThread().setContextClassLoader(old);
+        }
     }
 
     @Override
@@ -58,14 +82,37 @@ public class EntityManagerFactoryCallable implements Callable<EntityManagerFacto
             if (!ValidationMode.NONE.equals(unitInfo.getValidationMode())) {
                 properties.put("javax.persistence.validation.factory", new ValidatorFactoryWrapper(potentialValidators));
             }
+            if (cdi && "true".equalsIgnoreCase(unitInfo.getProperties().getProperty("tomee.jpa.cdi",
"true"))
+                    && "true".equalsIgnoreCase(SystemInstance.get().getProperty("tomee.jpa.cdi",
"true"))) {
+                properties.put("javax.persistence.bean.manager", // TODO: impl a passthrough
BM?
+                        Proxy.newProxyInstance(appClassLoader, new Class<?>[]{BeanManager.class},
new InvocationHandler() {
+                            private volatile BeanManager bm;
+
+                            @Override
+                            public Object invoke(final Object proxy, final Method method,
final Object[] args) throws Throwable {
+                                try {
+                                    return method.invoke(findBm(), args);
+                                } catch (final InvocationTargetException ite) {
+                                    Logger.getInstance(LogCategory.OPENEJB_JPA, EntityManagerFactoryCallable.class)
+                                            .warning("Exception calling CDI, if a lifecycle
issue you should maybe set tomee.jpa.factory.lazy=true", ite.getCause());
+                                    throw ite.getCause();
+                                }
+                            }
+
+                            private Object findBm() {
+                                return bm != null ? bm : (bm = new InjectableBeanManager(WebBeansContext.currentInstance().getBeanManagerImpl()));
+                            }
+                        })
+                );
+            }
 
             customizeProperties(properties);
 
             final EntityManagerFactory emf = persistenceProvider.createContainerEntityManagerFactory(unitInfo,
properties);
 
             if (unitInfo.getProperties() != null
-                && "true".equalsIgnoreCase(unitInfo.getProperties().getProperty(OPENEJB_JPA_INIT_ENTITYMANAGER))
-                || SystemInstance.get().getOptions().get(OPENEJB_JPA_INIT_ENTITYMANAGER,
false)) {
+                    && "true".equalsIgnoreCase(unitInfo.getProperties().getProperty(OPENEJB_JPA_INIT_ENTITYMANAGER))
+                    || SystemInstance.get().getOptions().get(OPENEJB_JPA_INIT_ENTITYMANAGER,
false)) {
                 emf.createEntityManager().close();
             }
 

http://git-wip-us.apache.org/repos/asf/tomee/blob/0737513a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java
index 992404e..5a54b21 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java
@@ -25,7 +25,6 @@ import org.apache.openejb.spi.ContainerSystem;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
 
-import java.util.Map;
 import javax.naming.Context;
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
@@ -35,6 +34,7 @@ import javax.persistence.spi.PersistenceUnitTransactionType;
 import javax.sql.CommonDataSource;
 import javax.sql.DataSource;
 import javax.validation.ValidatorFactory;
+import java.util.Map;
 
 public class PersistenceBuilder {
 
@@ -50,7 +50,8 @@ public class PersistenceBuilder {
     }
 
     public ReloadableEntityManagerFactory createEntityManagerFactory(final PersistenceUnitInfo
info, final ClassLoader classLoader,
-                                                                     final Map<ComparableValidationConfig,
ValidatorFactory> validators) throws Exception {
+                                                                     final Map<ComparableValidationConfig,
ValidatorFactory> validators,
+                                                                     final boolean hasCdi)
throws Exception {
         final PersistenceUnitInfoImpl unitInfo = new PersistenceUnitInfoImpl(persistenceClassLoaderHandler);
 
         // Persistence Unit Id
@@ -68,7 +69,7 @@ public class PersistenceBuilder {
         // Exclude Unlisted Classes
         unitInfo.setExcludeUnlistedClasses(info.excludeUnlistedClasses);
 
-        unitInfo.setLazilyInitialized(info.webappName != null);
+        unitInfo.setLazilyInitialized(info.webappName != null || "true".equalsIgnoreCase(info.properties.getProperty("tomee.jpa.factory.lazy",
"false")));
 
         final Context context = SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext();
 
@@ -151,7 +152,7 @@ public class PersistenceBuilder {
         final String persistenceProviderClassName = unitInfo.getPersistenceProviderClassName();
         unitInfo.setPersistenceProviderClassName(persistenceProviderClassName);
 
-        final EntityManagerFactoryCallable callable = new EntityManagerFactoryCallable(persistenceProviderClassName,
unitInfo, classLoader, validators);
+        final EntityManagerFactoryCallable callable = new EntityManagerFactoryCallable(persistenceProviderClassName,
unitInfo, classLoader, validators, hasCdi);
         return new ReloadableEntityManagerFactory(classLoader, callable, unitInfo);
     }
 

http://git-wip-us.apache.org/repos/asf/tomee/blob/0737513a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ReloadableEntityManagerFactory.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ReloadableEntityManagerFactory.java
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ReloadableEntityManagerFactory.java
index c61b207..a9ba815 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ReloadableEntityManagerFactory.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ReloadableEntityManagerFactory.java
@@ -86,7 +86,7 @@ public class ReloadableEntityManagerFactory implements EntityManagerFactory,
Ser
 
     private final PersistenceUnitInfoImpl unitInfoImpl;
     private ClassLoader classLoader;
-    private EntityManagerFactory delegate;
+    private volatile EntityManagerFactory delegate;
     private final EntityManagerFactoryCallable entityManagerFactoryCallable;
     private ObjectName objectName;
 
@@ -112,6 +112,21 @@ public class ReloadableEntityManagerFactory implements EntityManagerFactory,
Ser
         unitInfoImpl.setClassLoader(loader);
     }
 
+    public EntityManagerFactoryCallable getEntityManagerFactoryCallable() {
+        return entityManagerFactoryCallable;
+    }
+
+    private EntityManagerFactory delegate() {
+        if (delegate == null) {
+            synchronized (this) {
+                if (delegate == null) {
+                    createDelegate();
+                }
+            }
+        }
+        return delegate;
+    }
+
     public void createDelegate() {
         JPAThreadContext.infos.put("properties", entityManagerFactoryCallable.getUnitInfo().getProperties());
         final long start = System.nanoTime();
@@ -145,7 +160,7 @@ public class ReloadableEntityManagerFactory implements EntityManagerFactory,
Ser
     public EntityManager createEntityManager() {
         EntityManager em;
         try {
-            em = delegate.createEntityManager();
+            em = delegate().createEntityManager();
         } catch (final LinkageError le) {
             em = delegate.createEntityManager();
         }
@@ -160,7 +175,7 @@ public class ReloadableEntityManagerFactory implements EntityManagerFactory,
Ser
     public EntityManager createEntityManager(final Map map) {
         EntityManager em;
         try {
-            em = delegate.createEntityManager(map);
+            em = delegate().createEntityManager(map);
         } catch (final LinkageError le) {
             em = delegate.createEntityManager(map);
         }
@@ -175,7 +190,7 @@ public class ReloadableEntityManagerFactory implements EntityManagerFactory,
Ser
     public EntityManager createEntityManager(final SynchronizationType synchronizationType)
{
         EntityManager em;
         try {
-            em = delegate.createEntityManager(synchronizationType);
+            em = delegate().createEntityManager(synchronizationType);
         } catch (final LinkageError le) {
             em = delegate.createEntityManager(synchronizationType);
         }
@@ -190,7 +205,7 @@ public class ReloadableEntityManagerFactory implements EntityManagerFactory,
Ser
     public EntityManager createEntityManager(final SynchronizationType synchronizationType,
final Map map) {
         EntityManager em;
         try {
-            em = delegate.createEntityManager(synchronizationType, map);
+            em = delegate().createEntityManager(synchronizationType, map);
         } catch (final LinkageError le) {
             em = delegate.createEntityManager(synchronizationType, map);
         }
@@ -206,56 +221,56 @@ public class ReloadableEntityManagerFactory implements EntityManagerFactory,
Ser
         if (cls.isAssignableFrom(getClass())) {
             return cls.cast(this);
         }
-        return delegate.unwrap(cls);
+        return delegate().unwrap(cls);
     }
 
     @Override
     public void addNamedQuery(final String name, final Query query) {
-        delegate.addNamedQuery(name, query);
+        delegate().addNamedQuery(name, query);
     }
 
     @Override
     public <T> void addNamedEntityGraph(final String graphName, final EntityGraph<T>
entityGraph) {
-        delegate.addNamedEntityGraph(graphName, entityGraph);
+        delegate().addNamedEntityGraph(graphName, entityGraph);
     }
 
     @Override
     public CriteriaBuilder getCriteriaBuilder() {
-        return delegate.getCriteriaBuilder();
+        return delegate().getCriteriaBuilder();
     }
 
     @Override
     public Metamodel getMetamodel() {
-        return delegate.getMetamodel();
+        return delegate().getMetamodel();
     }
 
     @Override
     public boolean isOpen() {
-        return delegate.isOpen();
+        return delegate().isOpen();
     }
 
     @Override
     public void close() {
-        delegate.close();
+        delegate().close();
     }
 
     @Override
     public Map<String, Object> getProperties() {
-        return delegate.getProperties();
+        return delegate().getProperties();
     }
 
     @Override
     public Cache getCache() {
-        return delegate.getCache();
+        return delegate().getCache();
     }
 
     @Override
     public PersistenceUnitUtil getPersistenceUnitUtil() {
-        return delegate.getPersistenceUnitUtil();
+        return delegate().getPersistenceUnitUtil();
     }
 
     public EntityManagerFactory getDelegate() {
-        return delegate;
+        return delegate();
     }
 
     public void register() throws OpenEJBException {

http://git-wip-us.apache.org/repos/asf/tomee/blob/0737513a/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManager.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManager.java
b/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManager.java
index 208f6d5..79d3154 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManager.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/persistence/JtaEntityManager.java
@@ -120,13 +120,14 @@ public class JtaEntityManager implements EntityManager, Serializable
{
 
     public static boolean isJPA21(final EntityManagerFactory entityManagerFactory) {
         return ReloadableEntityManagerFactory.class.isInstance(entityManagerFactory) ?
-                isJPA21(ReloadableEntityManagerFactory.class.cast(entityManagerFactory).getDelegate())
-                : hasMethod(entityManagerFactory, "createEntityManager", SynchronizationType.class);
+                hasMethod(
+                        ReloadableEntityManagerFactory.class.cast(entityManagerFactory).getEntityManagerFactoryCallable().getProvider(),
+                        "createEntityManager", SynchronizationType.class)
+                : hasMethod(entityManagerFactory.getClass(), "createEntityManager", SynchronizationType.class);
     }
 
-    private static boolean hasMethod(final Object object, final String name, final Class<?>...
params) {
+    private static boolean hasMethod(final Class<?> objectClass, final String name,
final Class<?>... params) {
         try {
-            final Class<?> objectClass = object.getClass();
             Boolean result = IS_JPA21.get(objectClass);
             if (result == null) {
                 result = !Modifier.isAbstract(objectClass.getMethod(name, params).getModifiers());

http://git-wip-us.apache.org/repos/asf/tomee/blob/0737513a/container/openejb-core/src/test/java/org/apache/openejb/jpa/JPAHasBeanManagerTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/jpa/JPAHasBeanManagerTest.java
b/container/openejb-core/src/test/java/org/apache/openejb/jpa/JPAHasBeanManagerTest.java
new file mode 100644
index 0000000..9e42db3
--- /dev/null
+++ b/container/openejb-core/src/test/java/org/apache/openejb/jpa/JPAHasBeanManagerTest.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.openejb.jpa;
+
+import org.apache.openejb.api.configuration.PersistenceUnitDefinition;
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.testing.Classes;
+import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
+import org.apache.openjpa.persistence.PersistenceProviderImpl;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.annotation.PostConstruct;
+import javax.ejb.Singleton;
+import javax.ejb.Startup;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.Initialized;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+import javax.persistence.Entity;
+import javax.persistence.EntityManager;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.PersistenceContext;
+import javax.persistence.spi.PersistenceUnitInfo;
+import javax.transaction.Transactional;
+import java.util.Map;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@Classes(cdi = true, innerClassesAsBean = true)
+@RunWith(ApplicationComposer.class)
+public class JPAHasBeanManagerTest {
+    @Inject
+    private Dao dao;
+
+    @Test
+    public void run() {
+        dao.doAsserts();
+    }
+
+    @Transactional
+    @ApplicationScoped
+    @PersistenceUnitDefinition(
+            entitiesPackage = "org.apache.openejb.jpa",
+            properties = {"openjpa.RuntimeUnenhancedClasses=supported", "tomee.jpa.factory.lazy=true"},
+            provider = "org.apache.openejb.jpa.JPAHasBeanManagerTest$TheTestProvider")
+    public static class Dao {
+        @PersistenceContext
+        private EntityManager em;
+        private TheTestEntity persisted;
+
+        public void start(@Observes @Initialized(ApplicationScoped.class) final Object boot)
{
+            TheTestEntity entity = new TheTestEntity();
+            em.persist(entity); // ensure it works
+            persisted = entity;
+        }
+
+        public void doAsserts() {
+            assertNotNull(TheTestProvider.MAP);
+            final Object bm = TheTestProvider.MAP.get("javax.persistence.bean.manager");
+            assertNotNull(bm);
+            assertTrue(BeanManager.class.isInstance(bm));
+            assertNotNull(em.find(TheTestEntity.class, persisted.getId()));
+        }
+    }
+
+    @Startup
+    @Singleton
+    public static class EJBDao {
+        @PersistenceContext
+        private EntityManager em;
+
+        @PostConstruct
+        public void start() {
+            TheTestEntity entity = new TheTestEntity();
+            em.persist(entity); // ensure it works
+        }
+    }
+
+    public static class TheTestProvider extends PersistenceProviderImpl {
+        private static Map MAP;
+
+        @Override
+        public OpenJPAEntityManagerFactory createContainerEntityManagerFactory(final PersistenceUnitInfo
pui, final Map m) {
+            MAP = m;
+            // only works cause of lazy property
+            final BeanManager beanManager = BeanManager.class.cast(m.get("javax.persistence.bean.manager"));
+            assertNotNull(beanManager.getReference(beanManager.resolve(beanManager.getBeans(Dao.class)),
Dao.class, null));
+            // just delegate to openjpa since we don't aim at reimplementing JPA in a test
;)
+            return super.createContainerEntityManagerFactory(pui, m);
+        }
+    }
+
+    @Entity
+    public static class TheTestEntity {
+        @Id
+        @GeneratedValue
+        private long id;
+
+        public long getId() {
+            return id;
+        }
+    }
+}


Mime
View raw message