1

I want to migrate an existing single-tenant application to multi-tenant application.
The first step is to create a default tenant and get it connect to the application, the code is as following:

the model :

    @Entity
            @Multitenant(MultitenantType.TABLE_PER_TENANT)
            @TenantTableDiscriminator(type = SCHEMA, contextProperty = MULTITENANT_PROPERTY_DEFAULT)
            @Table(name = "UTILISATEUR")
    public class User implements Serializable {

  @SequenceGenerator(name = "USER_SEQ", sequenceName = "user_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_SEQ")
    @Column(name = "id", nullable = false)
    private Integer id;
    private String username;
    private String password;
     @ManyToMany
    @JoinTable(name = "user_roles", joinColumns = {
        @JoinColumn(name = "User_userid")}, inverseJoinColumns = {
        @JoinColumn(name = "Role_roleid")})
    private List<Role> roles;
     ..... }





 @Entity
    @Multitenant(MultitenantType.TABLE_PER_TENANT)
    @TenantTableDiscriminator(type = SCHEMA, contextProperty = MULTITENANT_PROPERTY_DEFAULT)
    public class Role implements Serializable { 

@Id
@SequenceGenerator(name = "ROLE_SEQ", sequenceName = "ROLE_SEQ", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ROLE_SEQ")
@Column(name = "id", nullable = false)
private Integer id; 
private String 
private String rolename;
@ManyToMany(mappedBy = "roles")
private List<User> users;
public Integer getId() {
        return id;
    }
    ....}

the persistence.xml file:

<?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
        <persistence-unit name="com.nz_war_1.0-SNAPSHOTPU" transaction-type="JTA">
             <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
            <jta-data-source>jdbc/SimpleCRUD_JDBC</jta-data-source>
            <exclude-unlisted-classes>false</exclude-unlisted-classes>
            <properties>
                <property name="eclipselink.logging.level" value="fine" />
                <property name="eclipselink.tenant-id"                     value="default_tenant" />
            </properties>
        </persistence-unit>
    </persistence>

I created a Singleton class to have the Entity Manager Factory:

   public class EmfProvider {

        private static final String DB_PU = "com.nz_war_1.0-SNAPSHOTPU";
        public static final boolean DEBUG = true;
        private static final EmfProvider singleton = new EmfProvider();
        private EntityManagerFactory emf;

        private EmfProvider() {
        }

        public static EmfProvider getInstance() {
            return singleton;
        }

        public EntityManagerFactory getEntityManagerFactory() {
            if (emf == null) {
                emf = Persistence.createEntityManagerFactory(DB_PU);
            }
            if (DEBUG) {
                System.out.println("factory created on: " + new Date());
            }
            return emf;
        }

        public void closeEmf() {
            if (emf.isOpen() || emf != null) {
                emf.close();
            }
            emf = null;
            if (DEBUG) {
                System.out.println("EMF closed at: " + new Date());
            }

        }
    }

The facade: Note that I don't user @persistenceContext, and create the entitymanager using the persistence unit manually because later we have to deterimine the persistenceuUnit to use programaticly:

 public abstract class DataAccessService<T> {
     private EntityManager em;
    public DataAccessService() {}
    private Class<T> type;
    public DataAccessService(Class<T> type) {
            this.type = type;
        }
    public void create(T t) {
            em = EmfProvider.getInstance().getEntityManagerFactory().createEntityManager();
        this.em.persist(t);
        this.em.flush();
    this.em.refresh(t);

  public List findWithNamedQuery(String namedQueryName) {
        em = EmfProvider.getInstance().getEntityManagerFactory().createEntityManager();
        return this.em.createNamedQuery(namedQueryName).getResultList();
    }
..........  
}

@Stateless

public class UserService extends DataAccessService<User>{

    public UserService(){
        super(User.class);
    }   
}

after running the project I get an exception which is: Predeployment of PersistenceUnit [com.nz_war_1.0-SNAPSHOTPU] failed.
and a long error in glassfish log:

    Avertissement: EJB5184:A system exception occurred during an invocation on EJB UserService, method: public java.util.List com.nz.simplecrud.service.DataAccessService.findWithNamedQuery(java.lang.String)
    Avertissement: javax.ejb.EJBException
        at com.sun.ejb.containers.BaseContainer.processSystemException(BaseContainer.java:5215)
        at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5113)
        at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4901)
        at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2045)
        at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1994)
        at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222)
        at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:89)
        at com.sun.proxy.$Proxy284.findWithNamedQuery(Unknown Source)
        at com.nz.simplecrud.service.__EJB31_Generated__UserService__Intf____Bean__.findWithNamedQuery(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:267)
        at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:52)
        at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:137)
        at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:263)
        at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:110)
        at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56)
        at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:105)
        at com.nz.simplecrud.service.UserService$Proxy$_$$_Weld$Proxy$.findWithNamedQuery(UserService$Proxy$_$$_Weld$Proxy$.java)
        at com.nz.simplecrud.controller.UserController.init(UserController.java:64)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)  
        ......

Caused by: Exception [EclipseLink-30005] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.PersistenceUnitLoadingException
Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [com.nz_war_1.0-SNAPSHOTPU] failed.
Internal Exception: Exception [EclipseLink-7161] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Entity class [class com.nz.simplecrud.entities.UserRoleView] has no primary key specified. It should define either an @Id, @EmbeddedId or an @IdClass. If you have defined PK using any of these annotations then make sure that you do not have mixed access-type (both fields and properties annotated) in your entity class hierarchy.
    at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:127)
    at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactoryImpl(PersistenceProvider.java:111)
    at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:183)  
....  
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [com.nz_war_1.0-SNAPSHOTPU] failed.
Internal Exception: Exception [EclipseLink-7161] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Entity class [class com.nz.simplecrud.entities.UserRoleView] has no primary key specified. It should define either an @Id, @EmbeddedId or an @IdClass. If you have defined PK using any of these annotations then make sure that you do not have mixed access-type (both fields and properties annotated) in your entity class hierarchy.
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.createPredeployFailedPersistenceException(EntityManagerSetupImpl.java:2023)
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:2014)  
Caused by: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [com.nz_war_1.0-SNAPSHOTPU] failed.
Internal Exception: Exception [EclipseLink-7161] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Entity class [class com.nz.simplecrud.entities.UserRoleView] has no primary key specified. It should define either an @Id, @EmbeddedId or an @IdClass. If you have defined PK using any of these annotations then make sure that you do not have mixed access-type (both fields and properties annotated) in your entity class hierarchy.
    at org.eclipse.persistence.exceptions.EntityManagerSetupException.predeployFailed(EntityManagerSetupException.java:231)
    ... 135 more
Caused by: Exception [EclipseLink-7161] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Entity class [class com.nz.simplecrud.entities.UserRoleView] has no primary key specified. It should define either an @Id, @EmbeddedId or an @IdClass. If you have defined PK using any of these annotations then make sure that you do not have mixed access-type (both fields and properties annotated) in your entity class hierarchy.
    at org.eclipse.persistence.exceptions.ValidationException.noPrimaryKeyAnnotationsFound(ValidationException.java:1425)  

Grave: Error Rendering View[/admin/UserList.xhtml]
javax.el.ELException: /admin/UserList.xhtml @12,69 value="#{userController.lazyModel}": org.jboss.weld.exceptions.WeldException: WELD-000049 Unable to invoke [method] @PostConstruct public com.nz.simplecrud.controller.UserController.init() on com.nz.simplecrud.controller.UserController@519c628d
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)....  

Grave: Error Rendering View[/admin/UserList.xhtml]
javax.el.ELException: /admin/UserList.xhtml @12,69 value="#{userController.lazyModel}": org.jboss.weld.exceptions.WeldException: WELD-000049 Unable to invoke [method] @PostConstruct public com.nz.simplecrud.controller.UserController.init() on com.nz.simplecrud.controller.UserController@5bcd013b
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
    at javax.faces.component.UIData.getValue(UIData.java:731)....
Caused by: org.jboss.weld.exceptions.WeldException: WELD-000049 Unable to invoke [method] @PostConstruct public com.nz.simplecrud.controller.UserController.init() on com.nz.simplecrud.controller.UserController@5bcd013b
    at org.jboss.weld.bean.AbstractClassBean.defaultPostConstruct(AbstractClassBean.java:400)
    at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.postConstruct(ManagedBean.java:174)
    at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:294)
    at org.jboss.weld.context.AbstractContext.get(AbstractContext.java:107)

Can any one help me please. Thank you.

user_24434
  • 87
  • 8
  • The EJB exception doesn't seem very useful - is there an internal exception being printed in the logs further down? Can you try catching and printing off exceptions within the findWithNamedQuery method? – Chris Apr 01 '15 at 19:05
  • @Chris, I have just right now editted the post and add more exceptions printed in the logs in order to make you see it more clear, sorry for the long details , I would appreciate your help very much. – user_24434 Apr 01 '15 at 23:33
  • The exceptions you posted states your UserRoleView entity is incomplete and missing a ID annotation – Chris Apr 02 '15 at 15:28
  • In fact a view is not a physic table so why does it require an id column? secondly, the application works correctly without this configuration of multitenancy. Only when I added the @multitenant(table-per-tenant,...) , the "" in persistence.xmml and the EmfProvider class I got errors, otherwise nothing is wrong. So maybe the way I'm adding multitenancy is wrong. Could you correct me please ! – user_24434 Apr 02 '15 at 15:51
  • If you mapped that class as an entity, it requires an identifier to be valid. I can't explain why you don't get this error without multitenant config; maybe you made other changes causing this class to be loaded when it wasn't before. All I can say is you need to correct the issue now. – Chris Apr 02 '15 at 17:58
  • that class was in the target folder, after deleting it those errors disappeared. Now I get this error: Exception [EclipseLink-53] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.DescriptorException Exception Description: The relation table name is not set for this mapping. Mapping: org.eclipse.persistence.mappings.ManyToManyMapping[users] Descriptor: RelationalDescriptor(com.nz.simplecrud.entity.Role --> [DatabaseTable(default_tenant.ROLE)]) – user_24434 Apr 03 '15 at 14:23
  • 1
    Can't be of help with out the mappings from the Role class. – Chris Apr 03 '15 at 15:42

0 Answers0