You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2015/01/02 09:00:53 UTC

[1/2] syncope git commit: [SYNCOPE-620] JPA relationship tests in; persistence-jpa completed

Repository: syncope
Updated Branches:
  refs/heads/2_0_X 556d51862 -> ab462f08b


http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/TaskTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/TaskTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/TaskTest.java
new file mode 100644
index 0000000..f571f7d
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/TaskTest.java
@@ -0,0 +1,201 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.PropagationMode;
+import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.dao.TaskDAO;
+import org.apache.syncope.persistence.api.dao.TaskExecDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.persistence.api.entity.task.PushTask;
+import org.apache.syncope.persistence.api.entity.task.SyncTask;
+import org.apache.syncope.persistence.api.entity.task.TaskExec;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.task.JPAPropagationTask;
+import org.apache.syncope.persistence.jpa.entity.task.JPATaskExec;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.AttributeBuilder;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class TaskTest extends AbstractTest {
+
+    @Autowired
+    private TaskDAO taskDAO;
+
+    @Autowired
+    private TaskExecDAO taskExecDAO;
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Test
+    public void read() {
+        PropagationTask task = taskDAO.find(1L);
+        assertNotNull(task);
+
+        assertNotNull(task.getExecs());
+        assertFalse(task.getExecs().isEmpty());
+        assertEquals(1, task.getExecs().size());
+    }
+
+    @Test
+    public void save() {
+        ExternalResource resource = resourceDAO.find("ws-target-resource-1");
+        assertNotNull(resource);
+
+        User user = userDAO.find(2L);
+        assertNotNull(user);
+
+        PropagationTask task = new JPAPropagationTask();
+        task.setResource(resource);
+        task.setSubjectType(AttributableType.USER);
+        task.setPropagationMode(PropagationMode.TWO_PHASES);
+        task.setPropagationOperation(ResourceOperation.CREATE);
+        task.setAccountId("one@two.com");
+
+        Set<Attribute> attributes = new HashSet<>();
+        attributes.add(AttributeBuilder.build("testAttribute", "testValue1", "testValue2"));
+        attributes.add(AttributeBuilder.buildPassword("password".toCharArray()));
+        task.setAttributes(attributes);
+
+        task = taskDAO.save(task);
+        assertNotNull(task);
+
+        PropagationTask actual = taskDAO.find(task.getKey());
+        assertEquals(task, actual);
+
+        taskDAO.flush();
+
+        resource = resourceDAO.find("ws-target-resource-1");
+        assertTrue(taskDAO.findAll(resource, TaskType.PROPAGATION).contains(task));
+    }
+
+    @Test
+    public void addPropagationTaskExecution() {
+        PropagationTask task = taskDAO.find(1L);
+        assertNotNull(task);
+
+        int executionNumber = task.getExecs().size();
+
+        TaskExec execution = new JPATaskExec();
+        execution.setTask(task);
+        execution.setStatus(PropagationTaskExecStatus.CREATED.name());
+        task.addExec(execution);
+        execution.setStartDate(new Date());
+
+        taskDAO.save(task);
+        taskDAO.flush();
+
+        task = taskDAO.find(1L);
+        assertNotNull(task);
+
+        assertEquals(executionNumber + 1, task.getExecs().size());
+    }
+
+    @Test
+    public void addSyncTaskExecution() {
+        SyncTask task = taskDAO.find(4L);
+        assertNotNull(task);
+
+        int executionNumber = task.getExecs().size();
+
+        TaskExec execution = new JPATaskExec();
+        execution.setStatus("Text-free status");
+        execution.setTask(task);
+        task.addExec(execution);
+        execution.setMessage("A message");
+
+        taskDAO.save(task);
+        taskDAO.flush();
+
+        task = taskDAO.find(4L);
+        assertNotNull(task);
+
+        assertEquals(executionNumber + 1, task.getExecs().size());
+    }
+
+    @Test
+    public void addPushTaskExecution() {
+        PushTask task = taskDAO.find(13L);
+        assertNotNull(task);
+
+        int executionNumber = task.getExecs().size();
+
+        TaskExec execution = new JPATaskExec();
+        execution.setStatus("Text-free status");
+        execution.setTask(task);
+        task.addExec(execution);
+        execution.setMessage("A message");
+
+        taskDAO.save(task);
+        taskDAO.flush();
+
+        task = taskDAO.find(13L);
+        assertNotNull(task);
+
+        assertEquals(executionNumber + 1, task.getExecs().size());
+    }
+
+    @Test
+    public void deleteTask() {
+        taskDAO.delete(1L);
+
+        taskDAO.flush();
+
+        assertNull(taskDAO.find(1L));
+        assertNull(taskExecDAO.find(1L));
+    }
+
+    @Test
+    public void deleteTaskExecution() {
+        TaskExec execution = taskExecDAO.find(1L);
+        int executionNumber = execution.getTask().getExecs().size();
+
+        taskExecDAO.delete(1L);
+
+        taskExecDAO.flush();
+
+        assertNull(taskExecDAO.find(1L));
+
+        PropagationTask task = taskDAO.find(1L);
+        assertEquals(task.getExecs().size(), executionNumber - 1);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/UserTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/UserTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/UserTest.java
new file mode 100644
index 0000000..bc1dad4
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/UserTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.dao.PlainAttrDAO;
+import org.apache.syncope.persistence.api.dao.PlainAttrValueDAO;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.user.UPlainSchema;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class UserTest extends AbstractTest {
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    @Autowired
+    private PlainAttrDAO plainAttrDAO;
+
+    @Autowired
+    private PlainAttrValueDAO plainAttrValueDAO;
+
+    @Test
+    public void test() {
+        userDAO.delete(4L);
+
+        userDAO.flush();
+
+        assertNull(userDAO.find(4L));
+        assertNull(plainAttrDAO.find(550L, UPlainAttr.class));
+        assertNull(plainAttrValueDAO.find(22L, UPlainAttrValue.class));
+        assertNotNull(plainSchemaDAO.find("loginDate", UPlainSchema.class));
+
+        List<Membership> memberships = roleDAO.findMemberships(roleDAO.find(7L));
+        assertTrue(memberships.isEmpty());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/resources/content.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/resources/content.xml b/syncope620/server/persistence-jpa/src/test/resources/content.xml
index 80e1d19..4f024e0 100644
--- a/syncope620/server/persistence-jpa/src/test/resources/content.xml
+++ b/syncope620/server/persistence-jpa/src/test/resources/content.xml
@@ -605,7 +605,7 @@ under the License.
                     creator="admin" lastModifier="admin" 
                     creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
   <ExternalResource_PropActions externalResource_name="resource-ldap"
-                                action="org.apache.syncope.core.propagation.impl.LDAPMembershipPropagationActions"/>
+                                action="org.apache.syncope.provisioning.api.propagation.PropagationActions"/>
   <ExternalResource name="ws-target-resource-nopropagation" connector_id="103"
                     randomPwdIfNotProvided="0" enforceMandatoryCondition="1" propagationMode="TWO_PHASES"
                     propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL" 
@@ -903,7 +903,7 @@ under the License.
         xmlAttributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"type","value":["type"]}]'/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="4" name="CSV (update matching; assign unmatching)" resource_name="resource-csv"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" fullReconciliation="0"
-        jobClassName="org.apache.syncope.core.sync.impl.SyncJob" unmatchingRule="ASSIGN" matchingRule="UPDATE"
+        jobClassName="org.apache.syncope.provisioning.api.job.SyncJob" unmatchingRule="ASSIGN" matchingRule="UPDATE"
         userTemplate='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"id":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"attributes":[{"schema":"type","readonly":false,"values":["email == &apos;test8@syncope.apache.org&apos;? &apos;TYPE_8&apos;: &apos;TYPE_OTHER&apos;"]}],"derivedAttributes":[{"schema":"cn","readonly":false,"values":[null]}],"virtualAttributes":[],"resources":["resource-testdb"],"propagationStatuses":[],"memberships":[{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"id":0,"roleId":8,"roleName":null,"attributes":[{"schema":"subscriptionDate","readonly":false,"values":["&apos;2009-08-18T16:33:12.203+0200&apos;"]}],"derivedAttributes":[],"virtualAttributes":[]}]}'
         roleTemplate='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"id":0,"name":null,"parent":0,"userOwner":null,"roleOwner":null,"inheritOwner":false,"inheritTemplates":false,"inheritAttrs":false,"inheritDerAttrs":false,"inheritVirAttrs":false,"inheritPasswordPolicy":false,"inheritAccountPolicy":false,"passwordPolicy":null,"accountPolicy":null,"attributes":[],"derivedAttributes":[],"virtualAttributes":[],"resources":[],"propagationStatuses":[],"entitlements":[],"rAttrTemplates":[],"rDerAttrTemplates":[],"rVirAttrTemplates":[],"mAttrTemplates":[],"mDerAttrTemplates":[],"mVirAttrTemplates":[]}'/>
   <Task DTYPE="SchedTask" type="SCHEDULED" id="5" name="SampleJob Task" jobClassName="org.apache.syncope.core.quartz.SampleJob" cronExpression="0 0 0 1 * ?"/>
@@ -913,81 +913,81 @@ under the License.
   <TaskExec id="6" task_id="6" status="SUCCESS"/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="7" name="TestDB Task" resource_name="resource-testdb"
         performCreate="1" performUpdate="1" performDelete="0" syncStatus="1" fullReconciliation="1"
-        jobClassName="org.apache.syncope.core.sync.impl.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"
+        jobClassName="org.apache.syncope.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"
         userTemplate='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"id":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"attributes":[{"schema":"type","readonly":false,"values":["&apos;type a&apos;"]},{"schema":"userId","readonly":false,"values":["&apos;reconciled@syncope.apache.org&apos;"]},{"schema":"fullname","readonly":false,"values":["&apos;reconciled fullname&apos;"]},{"schema":"surname","readonly":false,"values":["&apos;surname&apos;"]}],"derivedAttributes":[],"virtualAttributes":[],"resources":[],"propagationStatuses":[],"memberships":[]}'
         roleTemplate='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"id":0,"name":null,"parent":0,"userOwner":null,"roleOwner":null,"inheritOwner":false,"inheritTemplates":false,"inheritAttrs":false,"inheritDerAttrs":false,"inheritVirAttrs":false,"inheritPasswordPolicy":false,"inheritAccountPolicy":false,"passwordPolicy":null,"accountPolicy":null,"attributes":[],"derivedAttributes":[],"virtualAttributes":[],"resources":[],"propagationStatuses":[],"entitlements":[],"rAttrTemplates":[],"rDerAttrTemplates":[],"rVirAttrTemplates":[],"mAttrTemplates":[],"mDerAttrTemplates":[],"mVirAttrTemplates":[]}'/>
   <Task DTYPE="NotificationTask" type="NOTIFICATION" id="8" sender="admin@prova.org" subject="Notification for SYNCOPE-81" 
         textBody="NOTIFICATION-81" htmlBody="NOTIFICATION-81" traceLevel="ALL"/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="9" name="TestDB2 Task" resource_name="resource-testdb2"
         performCreate="1" performUpdate="1" performDelete="0" syncStatus="1" fullReconciliation="1"
-        jobClassName="org.apache.syncope.core.sync.impl.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
+        jobClassName="org.apache.syncope.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="10" name="TestDB Sync Task" resource_name="resource-db-sync"
         fullReconciliation="1" performCreate="1" performDelete="1" performUpdate="1" syncStatus="0"
-        jobClassName="org.apache.syncope.core.sync.impl.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
+        jobClassName="org.apache.syncope.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="11" name="LDAP Sync Task" resource_name="resource-ldap"
         fullReconciliation="1" performCreate="1" performDelete="1" performUpdate="1" syncStatus="0"
-        jobClassName="org.apache.syncope.core.sync.impl.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"
+        jobClassName="org.apache.syncope.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"
         userTemplate='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"id":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"attributes":[],"derivedAttributes":[],"virtualAttributes":[{"schema":"virtualReadOnly","readonly":false,"values":[""]}],"resources":["resource-ldap"],"propagationStatuses":[],"memberships":[]}'
         roleTemplate='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"id":0,"name":null,"parent":8,"userOwner":null,"roleOwner":null,"inheritOwner":false,"inheritTemplates":false,"inheritAttrs":false,"inheritDerAttrs":false,"inheritVirAttrs":false,"inheritPasswordPolicy":false,"inheritAccountPolicy":false,"passwordPolicy":null,"accountPolicy":null,"attributes":[{"schema":"show","readonly":false,"values":["&apos;true&apos;"]}],"derivedAttributes":[],"virtualAttributes":[],"resources":[],"propagationStatuses":[],"entitlements":[],"rAttrTemplates":["show"],"rDerAttrTemplates":[],"rVirAttrTemplates":[],"mAttrTemplates":[],"mDerAttrTemplates":[],"mVirAttrTemplates":[]}'/>
   <SyncTask_actionsClassNames SyncTask_id="11" actionClassName="org.apache.syncope.core.sync.impl.LDAPMembershipSyncActions"/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="12" name="VirAttrCache test" resource_name="resource-csv"
         performCreate="0" performUpdate="1" performDelete="0" syncStatus="0" fullReconciliation="1"
-        jobClassName="org.apache.syncope.core.sync.impl.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
+        jobClassName="org.apache.syncope.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
   <Task DTYPE="PushTask" type="PUSH" id="13" name="Export on resource-testdb2" resource_name="resource-testdb2"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
-        jobClassName="org.apache.syncope.core.sync.impl.PushJob" unmatchingRule="ASSIGN" matchingRule="IGNORE" 
+        jobClassName="org.apache.syncope.provisioning.api.job.PushJob" unmatchingRule="ASSIGN" matchingRule="IGNORE" 
         userFilter="surname==Vivaldi" roleFilter="name==_NO_ONE_"/>
   <Task DTYPE="PushTask" type="PUSH" id="14" name="Export on resource-testdb2" resource_name="resource-testdb2"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
-        jobClassName="org.apache.syncope.core.sync.impl.PushJob" unmatchingRule="PROVISION" matchingRule="IGNORE" 
+        jobClassName="org.apache.syncope.provisioning.api.job.PushJob" unmatchingRule="PROVISION" matchingRule="IGNORE" 
         userFilter="surname==Bellini" roleFilter="name==_NO_ONE_"/>
   <Task DTYPE="PushTask" type="PUSH" id="15" name="Export on resource-testdb2" resource_name="resource-testdb2"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
-        jobClassName="org.apache.syncope.core.sync.impl.PushJob" unmatchingRule="UNLINK" matchingRule="IGNORE" 
+        jobClassName="org.apache.syncope.provisioning.api.job.PushJob" unmatchingRule="UNLINK" matchingRule="IGNORE" 
         userFilter="surname==Puccini" roleFilter="name==_NO_ONE_"/>
   <Task DTYPE="PushTask" type="PUSH" id="16" name="Export on resource-testdb2" resource_name="resource-testdb2"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
-        jobClassName="org.apache.syncope.core.sync.impl.PushJob" unmatchingRule="IGNORE" matchingRule="IGNORE" 
+        jobClassName="org.apache.syncope.provisioning.api.job.PushJob" unmatchingRule="IGNORE" matchingRule="IGNORE" 
         userFilter="surname==Verdi" roleFilter="name==_NO_ONE_"/>
   <Task DTYPE="PushTask" type="PUSH" id="17" name="Export on resource-testdb2" resource_name="resource-testdb2"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
-        jobClassName="org.apache.syncope.core.sync.impl.PushJob" unmatchingRule="ASSIGN" matchingRule="UPDATE" 
+        jobClassName="org.apache.syncope.provisioning.api.job.PushJob" unmatchingRule="ASSIGN" matchingRule="UPDATE" 
         userFilter="username==_NO_ONE_" roleFilter="name==_NO_ONE_"/>
   <Task DTYPE="PushTask" type="PUSH" id="18" name="Export on resource-testdb2" resource_name="resource-testdb2"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
-        jobClassName="org.apache.syncope.core.sync.impl.PushJob" unmatchingRule="IGNORE" matchingRule="DEPROVISION" 
+        jobClassName="org.apache.syncope.provisioning.api.job.PushJob" unmatchingRule="IGNORE" matchingRule="DEPROVISION" 
         userFilter="surname==Verdi" roleFilter="name==_NO_ONE_"/>
   <Task DTYPE="PushTask" type="PUSH" id="19" name="Export on resource-testdb2" resource_name="resource-testdb2"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
-        jobClassName="org.apache.syncope.core.sync.impl.PushJob" unmatchingRule="IGNORE" matchingRule="UNASSIGN" 
+        jobClassName="org.apache.syncope.provisioning.api.job.PushJob" unmatchingRule="IGNORE" matchingRule="UNASSIGN" 
         userFilter="surname==Rossini" roleFilter="name==_NO_ONE_"/>
   <Task DTYPE="PushTask" type="PUSH" id="20" name="Export on resource-testdb2" resource_name="resource-testdb2"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
-        jobClassName="org.apache.syncope.core.sync.impl.PushJob" unmatchingRule="IGNORE" matchingRule="LINK" 
+        jobClassName="org.apache.syncope.provisioning.api.job.PushJob" unmatchingRule="IGNORE" matchingRule="LINK" 
         userFilter="surname==Verdi" roleFilter="name==_NO_ONE_"/>
   <Task DTYPE="PushTask" type="PUSH" id="21" name="Export on resource-testdb2" resource_name="resource-testdb2"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
-        jobClassName="org.apache.syncope.core.sync.impl.PushJob" unmatchingRule="IGNORE" matchingRule="UNLINK" 
+        jobClassName="org.apache.syncope.provisioning.api.job.PushJob" unmatchingRule="IGNORE" matchingRule="UNLINK" 
         userFilter="surname==Verdi" roleFilter="name==_NO_ONE_"/>
   <Task DTYPE="PushTask" type="PUSH" id="22" name="Export on resource-testdb2" resource_name="resource-testdb2"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
-        jobClassName="org.apache.syncope.core.sync.impl.PushJob" unmatchingRule="IGNORE" matchingRule="UPDATE" 
+        jobClassName="org.apache.syncope.provisioning.api.job.PushJob" unmatchingRule="IGNORE" matchingRule="UPDATE" 
         userFilter="surname==Verdi" roleFilter="name==_NO_ONE_"/>
   <Task DTYPE="PushTask" type="PUSH" id="23" name="Export on resource-ldap" resource_name="resource-ldap"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
-        jobClassName="org.apache.syncope.core.sync.impl.PushJob" unmatchingRule="ASSIGN" matchingRule="UNLINK" 
+        jobClassName="org.apache.syncope.provisioning.api.job.PushJob" unmatchingRule="ASSIGN" matchingRule="UNLINK" 
         userFilter="username==_NO_ONE_" roleFilter="name==citizen"/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="24" name="CSV Task (update matching; provision unmatching)" resource_name="resource-csv"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" fullReconciliation="0"
-        jobClassName="org.apache.syncope.core.sync.impl.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"
+        jobClassName="org.apache.syncope.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"
         userTemplate='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"id":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"attributes":[{"schema":"firstname","readonly":false,"values":[""]},{"schema":"userId","readonly":false,"values":["&apos;test&apos;"]},{"schema":"fullname","readonly":false,"values":["&apos;test&apos;"]},{"schema":"surname","readonly":false,"values":["&apos;test&apos;"]}],"derivedAttributes":[],"virtualAttributes":[],"resources":["resource-testdb"],"propagationStatuses":[],"memberships":[]}'
         roleTemplate='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"id":0,"name":null,"parent":0,"userOwner":null,"roleOwner":null,"inheritOwner":false,"inheritTemplates":false,"inheritAttrs":false,"inheritDerAttrs":false,"inheritVirAttrs":false,"inheritPasswordPolicy":false,"inheritAccountPolicy":false,"passwordPolicy":null,"accountPolicy":null,"attributes":[],"derivedAttributes":[],"virtualAttributes":[],"resources":[],"propagationStatuses":[],"entitlements":[],"rAttrTemplates":[],"rDerAttrTemplates":[],"rVirAttrTemplates":[],"mAttrTemplates":[],"mDerAttrTemplates":[],"mVirAttrTemplates":[]}'/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="25" name="CSV (unlink matching; ignore unmatching)" resource_name="resource-csv"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" fullReconciliation="0"
-        jobClassName="org.apache.syncope.core.sync.impl.SyncJob" unmatchingRule="IGNORE" matchingRule="UNLINK"/>
+        jobClassName="org.apache.syncope.provisioning.api.job.SyncJob" unmatchingRule="IGNORE" matchingRule="UNLINK"/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="26" name="CSV (ignore matching; assign unmatching)" resource_name="resource-csv"
         performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" fullReconciliation="0"
-        jobClassName="org.apache.syncope.core.sync.impl.SyncJob" unmatchingRule="ASSIGN" matchingRule="IGNORE"/>
+        jobClassName="org.apache.syncope.provisioning.api.job.SyncJob" unmatchingRule="ASSIGN" matchingRule="IGNORE"/>
 
   <Notification id="1" active="1" recipientAttrName="email" recipientAttrType="UserSchema" selfAsRecipient="1" 
                 sender="admin@syncope.apache.org" subject="Password Reset request" template="requestPasswordReset" 
@@ -1011,7 +1011,7 @@ under the License.
   
   <Report id="1" name="test"/>
   <ReportletConfInstance id="1" Report_id="1" 
-                         serializedInstance='{"@class":"org.apache.syncope.common.report.UserReportletConf","name":"testUserReportlet","matchingCond":null,"attributes":["fullname","gender"],"derivedAttributes":["cn"],"virtualAttributes":["virtualdata"],"features":["id","username","workflowId","status","creationDate","lastLoginDate","changePwdDate","passwordHistorySize","failedLoginCount","memberships","resources"]}'/>
+                         serializedInstance='{"@class":"org.apache.syncope.common.lib.report.UserReportletConf","name":"testUserReportlet","matchingCond":null,"attributes":["fullname","gender"],"derivedAttributes":["cn"],"virtualAttributes":["virtualdata"],"features":["id","username","workflowId","status","creationDate","lastLoginDate","changePwdDate","passwordHistorySize","failedLoginCount","memberships","resources"]}'/>
   <ReportExec Report_id="1" id="1" status="SUCCESS" startDate="2012-02-26 15:40:04" endDate="2012-02-26 15:41:04"/>
   
   <SyncopeLogger logName="syncope.audit.[REST]:[EntitlementController]:[]:[getOwn]:[SUCCESS]" logLevel="DEBUG" logType="AUDIT"/>


[2/2] syncope git commit: [SYNCOPE-620] JPA relationship tests in; persistence-jpa completed

Posted by il...@apache.org.
[SYNCOPE-620] JPA relationship tests in; persistence-jpa completed


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

Branch: refs/heads/2_0_X
Commit: ab462f08bebe9675f1c19aa4ba3b9565d8af2a71
Parents: 556d518
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Fri Jan 2 09:00:34 2015 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Fri Jan 2 09:00:34 2015 +0100

----------------------------------------------------------------------
 .../persistence/api/RoleEntitlementUtil.java    |  14 +-
 .../persistence/jpa/dao/AbstractSubjectDAO.java |   2 -
 .../persistence/jpa/dao/JPAEntitlementDAO.java  |   2 +-
 .../syncope/persistence/jpa/dao/JPARoleDAO.java |   2 +-
 .../jpa/validation/entity/ReportValidator.java  |   2 +-
 .../src/main/resources/content.xml              | 112 +++----
 .../jpa/entity/AttributableSearchTest.java      |  46 +--
 .../persistence/jpa/entity/UserTest.java        |   6 +-
 .../persistence/jpa/relationship/AttrTest.java  | 197 ++++++++++++
 .../relationship/AttributableSearchTest.java    |  76 +++++
 .../jpa/relationship/ConnInstanceTest.java      | 103 +++++++
 .../jpa/relationship/DerSchemaTest.java         |  59 ++++
 .../jpa/relationship/MembershipTest.java        |  84 ++++++
 .../jpa/relationship/PlainSchemaTest.java       | 158 ++++++++++
 .../jpa/relationship/ReportTest.java            | 122 ++++++++
 .../jpa/relationship/ResourceTest.java          | 298 +++++++++++++++++++
 .../persistence/jpa/relationship/RoleTest.java  | 146 +++++++++
 .../jpa/relationship/SecurityQuestionTest.java  |  58 ++++
 .../persistence/jpa/relationship/TaskTest.java  | 201 +++++++++++++
 .../persistence/jpa/relationship/UserTest.java  |  72 +++++
 .../src/test/resources/content.xml              |  44 +--
 21 files changed, 1688 insertions(+), 116 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/RoleEntitlementUtil.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/RoleEntitlementUtil.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/RoleEntitlementUtil.java
index 4e65eb3..0b9fec8 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/RoleEntitlementUtil.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/RoleEntitlementUtil.java
@@ -35,15 +35,15 @@ public final class RoleEntitlementUtil {
 
     private static final Logger LOG = LoggerFactory.getLogger(RoleEntitlementUtil.class);
 
-    public static String getEntitlementNameFromRoleId(final Long roleId) {
-        return "ROLE_" + roleId;
+    public static String getEntitlementNameFromRoleKey(final Long roleKey) {
+        return "ROLE_" + roleKey;
     }
 
     public static boolean isRoleEntitlement(final String entitlementName) {
         return ROLE_ENTITLEMENT_NAME_PATTERN.matcher(entitlementName).matches();
     }
 
-    public static Long getRoleId(final String entitlementName) {
+    public static Long getRoleKey(final String entitlementName) {
         Long result = null;
 
         if (isRoleEntitlement(entitlementName)) {
@@ -57,12 +57,12 @@ public final class RoleEntitlementUtil {
         return result;
     }
 
-    public static Set<Long> getRoleIds(final Set<String> entitlements) {
+    public static Set<Long> getRoleKeys(final Set<String> entitlements) {
         Set<Long> result = new HashSet<>();
 
         for (String entitlement : entitlements) {
             if (isRoleEntitlement(entitlement)) {
-                Long roleId = getRoleId(entitlement);
+                Long roleId = getRoleKey(entitlement);
                 if (roleId != null) {
                     result.add(roleId);
                 }
@@ -72,12 +72,12 @@ public final class RoleEntitlementUtil {
         return result;
     }
 
-    public static Set<Long> getRoleIds(final List<Entitlement> entitlements) {
+    public static Set<Long> getRoleKeys(final List<Entitlement> entitlements) {
         Set<String> names = new HashSet<>(entitlements.size());
         for (Entitlement entitlement : entitlements) {
             names.add(entitlement.getKey());
         }
-        return getRoleIds(names);
+        return getRoleKeys(names);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java
index 53b2cc4..ac6ab68 100644
--- a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java
@@ -18,8 +18,6 @@
  */
 package org.apache.syncope.persistence.jpa.dao;
 
-import static org.apache.syncope.common.lib.types.AttrSchemaType.Double;
-
 import java.io.StringReader;
 import java.util.ArrayList;
 import java.util.Collections;

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAEntitlementDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAEntitlementDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAEntitlementDAO.java
index cb7b90e..4946dad 100644
--- a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAEntitlementDAO.java
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAEntitlementDAO.java
@@ -56,7 +56,7 @@ public class JPAEntitlementDAO extends AbstractDAO<Entitlement, String> implemen
     @Override
     public Entitlement saveRoleEntitlement(final Role role) {
         Entitlement roleEnt = new JPAEntitlement();
-        roleEnt.setKey(RoleEntitlementUtil.getEntitlementNameFromRoleId(role.getKey()));
+        roleEnt.setKey(RoleEntitlementUtil.getEntitlementNameFromRoleKey(role.getKey()));
         roleEnt.setDescription("Entitlement for managing role " + role.getKey());
 
         return save(roleEnt);

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPARoleDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPARoleDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPARoleDAO.java
index 96174fe..5e6209c 100644
--- a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPARoleDAO.java
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPARoleDAO.java
@@ -515,7 +515,7 @@ public class JPARoleDAO extends AbstractSubjectDAO<RPlainAttr, RDerAttr, RVirAtt
             roleToBeDeleted.setRoleOwner(null);
             entityManager.remove(roleToBeDeleted);
 
-            entitlementDAO.delete(RoleEntitlementUtil.getEntitlementNameFromRoleId(roleToBeDeleted.getKey()));
+            entitlementDAO.delete(RoleEntitlementUtil.getEntitlementNameFromRoleKey(roleToBeDeleted.getKey()));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportValidator.java
index 7d2aa74..9ae5cd6 100644
--- a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportValidator.java
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportValidator.java
@@ -48,7 +48,7 @@ public class ReportValidator extends AbstractValidator<ReportCheck, Report> {
             }
         }
 
-        Set<String> reportletNames = new HashSet<String>();
+        Set<String> reportletNames = new HashSet<>();
         for (ReportletConf conf : object.getReportletConfs()) {
             reportletNames.add(conf.getName());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/main/resources/content.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/content.xml b/syncope620/server/persistence-jpa/src/main/resources/content.xml
index 827e6c9..31919f4 100644
--- a/syncope620/server/persistence-jpa/src/main/resources/content.xml
+++ b/syncope620/server/persistence-jpa/src/main/resources/content.xml
@@ -22,80 +22,80 @@ under the License.
                creator="admin" lastModifier="admin"
                creationDate="2014-06-20 11:00:00" lastChangeDate="2014-06-20 11:00:00"/>
 
-  <CSchema name="password.cipher.algorithm" type="String"
-           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
-  <CAttr id="1" owner_id="1" schema_name="password.cipher.algorithm"/>
-  <CAttrValue id="1" attribute_id="1" stringValue="SHA1"/>
+  <CPlainSchema name="password.cipher.algorithm" type="String"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="1" owner_id="1" schema_name="password.cipher.algorithm"/>
+  <CPlainAttrValue id="1" attribute_id="1" stringValue="SHA1"/>
 
   <!-- notificationjob.cronExpression:
   + not existing: NotificationJob runs according to Notification.DEFAULT_CRON_EXP
   + provided as empty string: NotificationJob disabled
   + provided as non-empty string: NotificationJob runs according to the given value -->
-  <CSchema name="notificationjob.cronExpression" type="String"
-           mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
-  <CAttr id="2" owner_id="1" schema_name="notificationjob.cronExpression"/>
-  <CAttrValue id="2" attribute_id="2" stringValue=""/>
+  <CPlainSchema name="notificationjob.cronExpression" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="2" owner_id="1" schema_name="notificationjob.cronExpression"/>
+  <CPlainAttrValue id="2" attribute_id="2" stringValue=""/>
 
-  <CSchema name="notification.maxRetries" type="Long"
-           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
-  <CAttr id="3" owner_id="1" schema_name="notification.maxRetries"/>
-  <CAttrValue id="3" attribute_id="3" longValue="0"/>
+  <CPlainSchema name="notification.maxRetries" type="Long"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="3" owner_id="1" schema_name="notification.maxRetries"/>
+  <CPlainAttrValue id="3" attribute_id="3" longValue="3"/>
 
-  <CSchema name="token.length" type="Long"
-           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
-  <CAttr id="4" owner_id="1" schema_name="token.length"/>
-  <CAttrValue id="4" attribute_id="4" longValue="256"/>
+  <CPlainSchema name="token.length" type="Long"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="4" owner_id="1" schema_name="token.length"/>
+  <CPlainAttrValue id="4" attribute_id="4" longValue="256"/>
 
-  <CSchema name="token.expireTime" type="Long"
-           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
-  <CAttr id="5" owner_id="1" schema_name="token.expireTime"/>
-  <CAttrValue id="5" attribute_id="5" longValue="60"/>
+  <CPlainSchema name="token.expireTime" type="Long"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="5" owner_id="1" schema_name="token.expireTime"/>
+  <CPlainAttrValue id="5" attribute_id="5" longValue="60"/>
 
-  <CSchema name="selfRegistration.allowed" type="Boolean"
-           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
-  <CAttr id="6" owner_id="1" schema_name="selfRegistration.allowed"/>
-  <CAttrValue id="6" attribute_id="6" booleanValue="1"/>
+  <CPlainSchema name="selfRegistration.allowed" type="Boolean"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="6" owner_id="1" schema_name="selfRegistration.allowed"/>
+  <CPlainAttrValue id="6" attribute_id="6" booleanValue="1"/>
 
-  <CSchema name="passwordReset.allowed" type="Boolean"
-           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
-  <CAttr id="7" owner_id="1" schema_name="passwordReset.allowed"/>
-  <CAttrValue id="7" attribute_id="7" booleanValue="1"/>
+  <CPlainSchema name="passwordReset.allowed" type="Boolean"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="7" owner_id="1" schema_name="passwordReset.allowed"/>
+  <CPlainAttrValue id="7" attribute_id="7" booleanValue="1"/>
 
-  <CSchema name="passwordReset.securityQuestion" type="Boolean"
-           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
-  <CAttr id="8" owner_id="1" schema_name="passwordReset.securityQuestion"/>
-  <CAttrValue id="8" attribute_id="8" booleanValue="1"/>
+  <CPlainSchema name="passwordReset.securityQuestion" type="Boolean"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="8" owner_id="1" schema_name="passwordReset.securityQuestion"/>
+  <CPlainAttrValue id="8" attribute_id="8" booleanValue="1"/>
 
-  <CSchema name="authentication.statuses" type="String"
-           mandatoryCondition="true" multivalue="1" uniqueConstraint="0" readonly="0"/>
-  <CAttr id="9" owner_id="1" schema_name="authentication.statuses"/>
-  <CAttrValue id="9" attribute_id="9" stringValue="created"/>
-  <CAttrValue id="10" attribute_id="9" stringValue="active"/>
+  <CPlainSchema name="authentication.statuses" type="String"
+                mandatoryCondition="true" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="9" owner_id="1" schema_name="authentication.statuses"/>
+  <CPlainAttrValue id="9" attribute_id="9" stringValue="created"/>
+  <CPlainAttrValue id="10" attribute_id="9" stringValue="active"/>
 
   <!-- Save user login date upon successful authentication -->
-  <CSchema name="log.lastlogindate" type="Boolean"
-           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
-  <CAttr id="11" owner_id="1" schema_name="log.lastlogindate"/>
-  <CAttrValue id="11" attribute_id="11" booleanValue="1"/>
+  <CPlainSchema name="log.lastlogindate" type="Boolean"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="11" owner_id="1" schema_name="log.lastlogindate"/>
+  <CPlainAttrValue id="11" attribute_id="11" booleanValue="1"/>
 
   <!-- For usage with admin console -->
-  <CSchema name="admin.user.layout" type="String"
-           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
-  <CSchema name="self.user.layout" type="String"
-           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
-  <CSchema name="admin.role.layout" type="String"
-           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
-  <CSchema name="self.role.layout" type="String"
-           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
-  <CSchema name="admin.membership.layout" type="String"
-           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
-  <CSchema name="self.membership.layout" type="String"
-           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainSchema name="admin.user.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainSchema name="self.user.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainSchema name="admin.role.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainSchema name="self.role.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainSchema name="admin.membership.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainSchema name="self.membership.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
         
   <!-- User pre-defined schemas -->
-  <USchema name="email" type="String"
-           mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
-           validatorClass="org.apache.syncope.core.persistence.validation.attrvalue.EmailAddressValidator"/>  
+  <UPlainSchema name="email" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+                validatorClass="org.apache.syncope.persistence.jpa.attrvalue.validation.EmailAddressValidator"/>
   
   <!-- Password reset notifications -->
   <Notification id="1" active="1" recipientAttrName="email" recipientAttrType="UserSchema" selfAsRecipient="1" 

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttributableSearchTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttributableSearchTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttributableSearchTest.java
index b4217fc..2f54395 100644
--- a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttributableSearchTest.java
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttributableSearchTest.java
@@ -116,7 +116,7 @@ public class AttributableSearchTest {
         assertTrue(cond.isValid());
 
         List<User> users =
-                searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), cond, SubjectType.USER);
+                searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), cond, SubjectType.USER);
         assertNotNull(users);
         assertEquals(1, users.size());
     }
@@ -131,7 +131,7 @@ public class AttributableSearchTest {
         assertTrue(cond.isValid());
 
         List<User> users =
-                searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), cond, SubjectType.USER);
+                searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), cond, SubjectType.USER);
         assertNotNull(users);
         assertEquals(4, users.size());
 
@@ -153,7 +153,7 @@ public class AttributableSearchTest {
         assertTrue(cond.isValid());
 
         List<User> users =
-                searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), cond, SubjectType.USER);
+                searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), cond, SubjectType.USER);
         assertNotNull(users);
         assertEquals(1, users.size());
 
@@ -182,13 +182,13 @@ public class AttributableSearchTest {
 
         assertTrue(cond.isValid());
 
-        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()),
                 cond, 1, 2, Collections.<OrderByClause>emptyList(),
                 SubjectType.USER);
         assertNotNull(users);
         assertEquals(1, users.size());
 
-        users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+        users = searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()),
                 cond, 2, 2, Collections.<OrderByClause>emptyList(),
                 SubjectType.USER);
         assertNotNull(users);
@@ -201,7 +201,7 @@ public class AttributableSearchTest {
         membershipCond.setRoleId(1L);
 
         List<User> users = searchDAO.search(
-                RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), SearchCond.getLeafCond(membershipCond),
+                RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), SearchCond.getLeafCond(membershipCond),
                 SubjectType.USER);
         assertNotNull(users);
         assertEquals(2, users.size());
@@ -210,7 +210,7 @@ public class AttributableSearchTest {
         membershipCond.setRoleId(5L);
 
         users = searchDAO.search(
-                RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), SearchCond.getNotLeafCond(membershipCond),
+                RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), SearchCond.getNotLeafCond(membershipCond),
                 SubjectType.USER);
         assertNotNull(users);
         assertEquals(5, users.size());
@@ -222,7 +222,7 @@ public class AttributableSearchTest {
         coolLeafCond.setSchema("cool");
 
         List<User> users = searchDAO.search(
-                RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), SearchCond.getLeafCond(coolLeafCond),
+                RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), SearchCond.getLeafCond(coolLeafCond),
                 SubjectType.USER);
         assertNotNull(users);
         assertEquals(4, users.size());
@@ -231,7 +231,7 @@ public class AttributableSearchTest {
         coolLeafCond.setSchema("cool");
 
         users = searchDAO.search(
-                RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), SearchCond.getLeafCond(coolLeafCond),
+                RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), SearchCond.getLeafCond(coolLeafCond),
                 SubjectType.USER);
         assertNotNull(users);
         assertEquals(1, users.size());
@@ -250,7 +250,7 @@ public class AttributableSearchTest {
         assertTrue(searchCondition.isValid());
 
         List<User> users = searchDAO.search(
-                RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), searchCondition,
+                RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), searchCondition,
                 SubjectType.USER);
 
         assertNotNull(users);
@@ -270,7 +270,7 @@ public class AttributableSearchTest {
         SearchCond searchCondition = SearchCond.getOrCond(SearchCond.getLeafCond(usernameLeafCond),
                 SearchCond.getLeafCond(idRightCond));
 
-        List<User> matchingUsers = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+        List<User> matchingUsers = searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()),
                 searchCondition, SubjectType.USER);
 
         assertNotNull(matchingUsers);
@@ -294,7 +294,7 @@ public class AttributableSearchTest {
 
         assertTrue(searchCondition.isValid());
 
-        List<Role> matchingRoles = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+        List<Role> matchingRoles = searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()),
                 searchCondition, SubjectType.ROLE);
 
         assertNotNull(matchingRoles);
@@ -317,7 +317,7 @@ public class AttributableSearchTest {
                 SearchCond.getLeafCond(idRightCond));
 
         List<User> matchingUsers =
-                searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), searchCondition,
+                searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), searchCondition,
                         SubjectType.USER);
 
         assertNotNull(matchingUsers);
@@ -334,7 +334,7 @@ public class AttributableSearchTest {
         assertTrue(searchCondition.isValid());
 
         List<User> users =
-                searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), searchCondition,
+                searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), searchCondition,
                         SubjectType.USER);
 
         assertNotNull(users);
@@ -348,7 +348,7 @@ public class AttributableSearchTest {
         searchCondition = SearchCond.getNotLeafCond(idLeafCond);
         assertTrue(searchCondition.isValid());
 
-        users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), searchCondition,
+        users = searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), searchCondition,
                 SubjectType.USER);
 
         assertNotNull(users);
@@ -383,10 +383,10 @@ public class AttributableSearchTest {
         orderByClause.setDirection(OrderByClause.Direction.ASC);
         orderByClauses.add(orderByClause);
 
-        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()),
                 searchCondition, Collections.singletonList(orderByClause),
                 SubjectType.USER);
-        assertEquals(searchDAO.count(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+        assertEquals(searchDAO.count(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()),
                 searchCondition, SubjectType.USER),
                 users.size());
     }
@@ -402,9 +402,9 @@ public class AttributableSearchTest {
         OrderByClause orderByClause = new OrderByClause();
         orderByClause.setField("name");
 
-        List<Role> roles = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+        List<Role> roles = searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()),
                 searchCondition, Collections.singletonList(orderByClause), SubjectType.ROLE);
-        assertEquals(searchDAO.count(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+        assertEquals(searchDAO.count(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()),
                 searchCondition, SubjectType.ROLE),
                 roles.size());
     }
@@ -421,7 +421,7 @@ public class AttributableSearchTest {
                 SearchCond.getAndCond(SearchCond.getNotLeafCond(ws2), SearchCond.getNotLeafCond(ws1));
         assertTrue(searchCondition.isValid());
 
-        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()),
                 searchCondition, SubjectType.USER);
         assertNotNull(users);
         assertEquals(2, users.size());
@@ -443,7 +443,7 @@ public class AttributableSearchTest {
         SearchCond searchCondition = SearchCond.getLeafCond(cond);
         assertTrue(searchCondition.isValid());
 
-        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()),
                 searchCondition, SubjectType.USER);
         assertNotNull(users);
         assertTrue(users.isEmpty());
@@ -458,7 +458,7 @@ public class AttributableSearchTest {
         SearchCond searchCondition = SearchCond.getLeafCond(cond);
         assertTrue(searchCondition.isValid());
 
-        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()),
                 searchCondition, SubjectType.USER);
         assertNotNull(users);
         assertEquals(1, users.size());
@@ -476,7 +476,7 @@ public class AttributableSearchTest {
         SearchCond searchCond = SearchCond.getOrCond(
                 SearchCond.getLeafCond(isNullCond), SearchCond.getLeafCond(likeCond));
 
-        Integer count = searchDAO.count(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), searchCond,
+        Integer count = searchDAO.count(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), searchCond,
                 SubjectType.USER);
         assertNotNull(count);
         assertTrue(count > 0);

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/UserTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/UserTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/UserTest.java
index 3acb870..cda790a 100644
--- a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/UserTest.java
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/UserTest.java
@@ -50,20 +50,20 @@ public class UserTest extends AbstractTest {
 
     @Test
     public void findAll() {
-        List<User> list = userDAO.findAll(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), 1, 100);
+        List<User> list = userDAO.findAll(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), 1, 100);
         assertEquals("did not get expected number of users ", 5, list.size());
     }
 
     @Test
     public void count() {
-        Integer count = userDAO.count(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()));
+        Integer count = userDAO.count(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()));
         assertNotNull(count);
         assertEquals(5, count.intValue());
     }
 
     @Test
     public void findAllByPageAndSize() {
-        Set<Long> allRoleIds = RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll());
+        Set<Long> allRoleIds = RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll());
 
         // get first page
         List<User> list = userDAO.findAll(allRoleIds, 1, 2);

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/AttrTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/AttrTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/AttrTest.java
new file mode 100644
index 0000000..c1fd3c9
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/AttrTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.persistence.api.dao.DerAttrDAO;
+import org.apache.syncope.persistence.api.dao.DerSchemaDAO;
+import org.apache.syncope.persistence.api.dao.MembershipDAO;
+import org.apache.syncope.persistence.api.dao.PlainAttrDAO;
+import org.apache.syncope.persistence.api.dao.PlainAttrValueDAO;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttr;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MPlainSchema;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.UDerAttr;
+import org.apache.syncope.persistence.api.entity.user.UDerSchema;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.JPAAttributableUtil;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUDerAttr;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUDerSchema;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class AttrTest extends AbstractTest {
+
+    @Autowired
+    private PlainAttrDAO plainAttrDAO;
+
+    @Autowired
+    private DerAttrDAO derAttrDAO;
+
+    @Autowired
+    private PlainAttrValueDAO plainAttrValueDAO;
+
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    @Autowired
+    private DerSchemaDAO derSchemaDAO;
+
+    @Autowired
+    private MembershipDAO membershipDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Test
+    public void deleteAttribute() {
+        plainAttrDAO.delete(117L, UPlainAttr.class);
+
+        plainAttrDAO.flush();
+
+        assertNull(plainAttrDAO.find(117L, UPlainAttr.class));
+        assertNull(plainAttrValueDAO.find(28L, UPlainAttrValue.class));
+    }
+
+    @Test
+    public void deleteAttributeValue() {
+        UPlainAttrValue value = plainAttrValueDAO.find(14L, UPlainAttrValue.class);
+        int attributeValueNumber = value.getAttr().getValues().size();
+
+        plainAttrValueDAO.delete(value.getKey(), UPlainAttrValue.class);
+
+        plainAttrValueDAO.flush();
+
+        assertNull(plainAttrValueDAO.find(value.getKey(), UPlainAttrValue.class));
+
+        UPlainAttr attribute = plainAttrDAO.find(104L, UPlainAttr.class);
+        assertEquals(attribute.getValues().size(), attributeValueNumber - 1);
+    }
+
+    @Test
+    public void checkForEnumType() {
+        User user = userDAO.find(1L);
+        Membership membership = user.getMembership(1L);
+        assertNotNull(membership);
+
+        MPlainSchema schema = new JPAMPlainSchema();
+        schema.setType(AttrSchemaType.Enum);
+        schema.setKey("color");
+        schema.setEnumerationValues("red" + SyncopeConstants.ENUM_VALUES_SEPARATOR + "yellow");
+
+        MPlainSchema actualSchema = plainSchemaDAO.save(schema);
+        assertNotNull(actualSchema);
+
+        MPlainAttrTemplate template = new JPAMPlainAttrTemplate();
+        template.setSchema(actualSchema);
+        membership.getRole().getAttrTemplates(MPlainAttrTemplate.class).add(template);
+
+        MPlainAttr attr = new JPAMPlainAttr();
+        attr.setTemplate(template);
+        attr.setOwner(membership);
+        attr.addValue("yellow", JPAAttributableUtil.getInstance(AttributableType.MEMBERSHIP));
+        membership.addPlainAttr(attr);
+
+        MPlainAttr actualAttribute = userDAO.save(user).getMembership(1L).getPlainAttr("color");
+        assertNotNull(actualAttribute);
+
+        membership = membershipDAO.find(1L);
+        assertNotNull(membership);
+        assertNotNull(membership.getPlainAttr(schema.getKey()));
+        assertNotNull(membership.getPlainAttr(schema.getKey()).getValues());
+
+        assertEquals(membership.getPlainAttr(schema.getKey()).getValues().size(), 1);
+    }
+
+    @Test
+    public void derAttrFromSpecialAttrs() {
+        UDerSchema sderived = new JPAUDerSchema();
+        sderived.setKey("sderived");
+        sderived.setExpression("username + ' - ' + creationDate + '[' + failedLogins + ']'");
+
+        sderived = derSchemaDAO.save(sderived);
+        derSchemaDAO.flush();
+
+        UDerSchema actual = derSchemaDAO.find("sderived", UDerSchema.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(sderived, actual);
+
+        User owner = userDAO.find(3L);
+        assertNotNull("did not get expected user", owner);
+
+        UDerAttr derAttr = new JPAUDerAttr();
+        derAttr.setOwner(owner);
+        derAttr.setSchema(sderived);
+
+        derAttr = derAttrDAO.save(derAttr);
+        derAttrDAO.flush();
+
+        derAttr = derAttrDAO.find(derAttr.getKey(), UDerAttr.class);
+        assertNotNull("expected save to work", derAttr);
+
+        String value = derAttr.getValue(owner.getPlainAttrs());
+        assertNotNull(value);
+        assertFalse(value.isEmpty());
+        assertTrue(value.startsWith("vivaldi - 2010-10-20"));
+        assertTrue(value.endsWith("[0]"));
+    }
+
+    @Test
+    public void unmatchedRoleAttr() {
+        Role role = roleDAO.find(1L);
+        assertNotNull(role);
+
+        assertNotNull(role.getAttrTemplate(RPlainAttrTemplate.class, "icon"));
+        assertNotNull(role.getPlainAttr("icon"));
+
+        assertTrue(role.getAttrTemplates(RPlainAttrTemplate.class).
+                remove(role.getAttrTemplate(RPlainAttrTemplate.class, "icon")));
+
+        role = roleDAO.save(role);
+        roleDAO.flush();
+
+        assertNull(role.getAttrTemplate(RPlainAttrTemplate.class, "icon"));
+        assertNull(role.getPlainAttr("icon"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/AttributableSearchTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/AttributableSearchTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/AttributableSearchTest.java
new file mode 100644
index 0000000..97b6042
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/AttributableSearchTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.syncope.persistence.api.RoleEntitlementUtil;
+import org.apache.syncope.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.SubjectSearchDAO;
+import org.apache.syncope.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class AttributableSearchTest extends AbstractTest {
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Autowired
+    private SubjectSearchDAO searchDAO;
+
+    @Autowired
+    private EntitlementDAO entitlementDAO;
+
+    @Test
+    public void issueSYNCOPE95() {
+        Set<Role> roles = new HashSet<>(roleDAO.findAll());
+        for (Role role : roles) {
+            roleDAO.delete(role.getKey());
+        }
+        roleDAO.flush();
+
+        final AttributeCond coolLeafCond = new AttributeCond(AttributeCond.Type.EQ);
+        coolLeafCond.setSchema("cool");
+        coolLeafCond.setExpression("true");
+
+        final SearchCond cond = SearchCond.getLeafCond(coolLeafCond);
+        assertTrue(cond.isValid());
+
+        final List<User> users =
+                searchDAO.search(RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll()), cond, SubjectType.USER);
+        assertNotNull(users);
+        assertEquals(1, users.size());
+
+        assertEquals(Long.valueOf(4L), users.get(0).getKey());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ConnInstanceTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ConnInstanceTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ConnInstanceTest.java
new file mode 100644
index 0000000..a0fa69d
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ConnInstanceTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import org.apache.syncope.common.lib.types.ConnectorCapability;
+import org.apache.syncope.persistence.api.dao.ConnInstanceDAO;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class ConnInstanceTest extends AbstractTest {
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    @Autowired
+    private ConnInstanceDAO connInstanceDAO;
+
+    @Test
+    public void deleteCascade() {
+        ConnInstance connInstance = connInstanceDAO.find(103L);
+        assertNotNull(connInstance);
+
+        List<? extends ExternalResource> resources = connInstance.getResources();
+        assertNotNull(resources);
+        assertFalse(resources.isEmpty());
+
+        connInstanceDAO.delete(connInstance.getKey());
+
+        connInstanceDAO.flush();
+
+        ConnInstance actual = connInstanceDAO.find(103L);
+        assertNull(actual);
+
+        for (ExternalResource resource : resources) {
+            assertNull(resourceDAO.find(resource.getKey()));
+        }
+    }
+
+    /**
+     * Connector change used to miss connector bean registration.
+     *
+     * http://code.google.com/p/syncope/issues/detail?id=176
+     */
+    @Test
+    public void issue176() {
+        ConnInstance connInstance = connInstanceDAO.find(103L);
+        assertNotNull(connInstance);
+        assertTrue(connInstance.getCapabilities().isEmpty());
+
+        List<? extends ExternalResource> resources = connInstance.getResources();
+        assertNotNull(resources);
+        assertEquals(4, resources.size());
+        assertTrue(
+                "ws-target-resource-nopropagation".equalsIgnoreCase(resources.get(0).getKey())
+                || "ws-target-resource-nopropagation".equalsIgnoreCase(resources.get(1).getKey())
+                || "ws-target-resource-nopropagation".equalsIgnoreCase(resources.get(2).getKey())
+                || "ws-target-resource-nopropagation".equalsIgnoreCase(resources.get(3).getKey()));
+
+        connInstance.addCapability(ConnectorCapability.SEARCH);
+
+        connInstance = connInstanceDAO.save(connInstance);
+        assertNotNull(connInstance);
+        assertFalse(connInstance.getCapabilities().isEmpty());
+
+        resources = connInstance.getResources();
+        assertNotNull(resources);
+        assertEquals(4, resources.size());
+        assertTrue(
+                "ws-target-resource-nopropagation".equalsIgnoreCase(resources.get(0).getKey())
+                || "ws-target-resource-nopropagation".equalsIgnoreCase(resources.get(1).getKey())
+                || "ws-target-resource-nopropagation".equalsIgnoreCase(resources.get(2).getKey())
+                || "ws-target-resource-nopropagation".equalsIgnoreCase(resources.get(3).getKey()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/DerSchemaTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/DerSchemaTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/DerSchemaTest.java
new file mode 100644
index 0000000..685c2e2
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/DerSchemaTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertNull;
+
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.persistence.api.dao.DerAttrDAO;
+import org.apache.syncope.persistence.api.dao.DerSchemaDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.user.UDerAttr;
+import org.apache.syncope.persistence.api.entity.user.UDerSchema;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.JPAAttributableUtil;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class DerSchemaTest extends AbstractTest {
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private DerSchemaDAO derSchemaDAO;
+
+    @Autowired
+    private DerAttrDAO derAttrDAO;
+
+    @Test
+    public void test() {
+        UDerSchema schema = derSchemaDAO.find("cn", UDerSchema.class);
+
+        derSchemaDAO.delete(schema.getKey(), JPAAttributableUtil.getInstance(AttributableType.USER));
+
+        derSchemaDAO.flush();
+
+        assertNull(derSchemaDAO.find(schema.getKey(), UDerSchema.class));
+        assertNull(derAttrDAO.find(100L, UDerAttr.class));
+        assertNull(userDAO.find(3L).getDerAttr(schema.getKey()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/MembershipTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/MembershipTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/MembershipTest.java
new file mode 100644
index 0000000..77d77c0
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/MembershipTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertTrue;
+
+import org.apache.syncope.persistence.api.dao.MembershipDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMembership;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+
+
+@Transactional
+public class MembershipTest extends AbstractTest {
+
+    @Autowired
+    private MembershipDAO membershipDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Test
+    public void delete() {
+        Membership membership = membershipDAO.find(4L);
+        User user = membership.getUser();
+        Role role = membership.getRole();
+
+        membershipDAO.delete(4L);
+
+        membershipDAO.flush();
+
+        for (Membership m : user.getMemberships()) {
+            assertTrue(m.getKey() != 4L);
+        }
+        for (Membership m : roleDAO.findMemberships(role)) {
+            assertTrue(m.getKey() != 4L);
+        }
+    }
+
+    @Test
+    public void deleteAndCreate() {
+        Membership membership = membershipDAO.find(3L);
+        User user = membership.getUser();
+        Role role = membership.getRole();
+
+        // 1. delete that membership
+        membershipDAO.delete(membership.getKey());
+
+        // if not flushing here, the INSERT below will be executed
+        // before the DELETE above
+        membershipDAO.flush();
+
+        // 2. (in the same transaction) create new membership with same user
+        // and role (in order to check the UNIQE constraint on Membership)
+        membership = new JPAMembership();
+        membership.setUser(user);
+        membership.setRole(role);
+
+        membership = membershipDAO.save(membership);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/PlainSchemaTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/PlainSchemaTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/PlainSchemaTest.java
new file mode 100644
index 0000000..29fb41e
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/PlainSchemaTest.java
@@ -0,0 +1,158 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.dao.PlainAttrDAO;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.MappingItem;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainSchema;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.JPAAttributableUtil;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class PlainSchemaTest extends AbstractTest {
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    @Autowired
+    private PlainAttrDAO plainAttrDAO;
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    @Test
+    public void deleteFullname() {
+        // fullname is mapped as AccountId for ws-target-resource-2, need to swap it otherwise validation errors 
+        // will be raised
+        for (MappingItem item : resourceDAO.find("ws-target-resource-2").getUmapping().getItems()) {
+            if ("fullname".equals(item.getIntAttrName())) {
+                item.setAccountid(false);
+            } else if ("surname".equals(item.getIntAttrName())) {
+                item.setAccountid(true);
+            }
+        }
+
+        // search for user schema fullname
+        UPlainSchema schema = plainSchemaDAO.find("fullname", UPlainSchema.class);
+        assertNotNull(schema);
+
+        // check for associated mappings
+        Set<MappingItem> mapItems = new HashSet<>();
+        for (ExternalResource resource : resourceDAO.findAll()) {
+            if (resource.getUmapping() != null) {
+                for (MappingItem mapItem : resource.getUmapping().getItems()) {
+                    if (schema.getKey().equals(mapItem.getIntAttrName())) {
+                        mapItems.add(mapItem);
+                    }
+                }
+            }
+        }
+        assertFalse(mapItems.isEmpty());
+
+        // delete user schema fullname
+        plainSchemaDAO.delete("fullname", JPAAttributableUtil.getInstance(AttributableType.USER));
+
+        plainSchemaDAO.flush();
+
+        // check for schema deletion
+        schema = plainSchemaDAO.find("fullname", UPlainSchema.class);
+        assertNull(schema);
+
+        plainSchemaDAO.clear();
+
+        // check for mappings deletion
+        mapItems = new HashSet<>();
+        for (ExternalResource resource : resourceDAO.findAll()) {
+            if (resource.getUmapping() != null) {
+                for (MappingItem mapItem : resource.getUmapping().getItems()) {
+                    if ("fullname".equals(mapItem.getIntAttrName())) {
+                        mapItems.add(mapItem);
+                    }
+                }
+            }
+        }
+        assertTrue(mapItems.isEmpty());
+
+        assertNull(plainAttrDAO.find(100L, UPlainAttr.class));
+        assertNull(plainAttrDAO.find(300L, UPlainAttr.class));
+        assertNull(userDAO.find(1L).getPlainAttr("fullname"));
+        assertNull(userDAO.find(3L).getPlainAttr("fullname"));
+    }
+
+    @Test
+    public void deleteSurname() {
+        // search for user schema fullname
+        UPlainSchema schema = plainSchemaDAO.find("surname", UPlainSchema.class);
+        assertNotNull(schema);
+
+        // check for associated mappings
+        Set<MappingItem> mappings = new HashSet<>();
+        for (ExternalResource resource : resourceDAO.findAll()) {
+            if (resource.getUmapping() != null) {
+                for (MappingItem mapItem : resource.getUmapping().getItems()) {
+                    if (schema.getKey().equals(mapItem.getIntAttrName())) {
+                        mappings.add(mapItem);
+                    }
+                }
+            }
+        }
+        assertFalse(mappings.isEmpty());
+
+        // delete user schema fullname
+        plainSchemaDAO.delete("surname", JPAAttributableUtil.getInstance(AttributableType.USER));
+
+        plainSchemaDAO.flush();
+
+        // check for schema deletion
+        schema = plainSchemaDAO.find("surname", UPlainSchema.class);
+        assertNull(schema);
+    }
+
+    @Test
+    public void deleteALong() {
+        assertEquals(6, resourceDAO.find("resource-db-sync").getUmapping().getItems().size());
+
+        plainSchemaDAO.delete("aLong", JPAAttributableUtil.getInstance(AttributableType.USER));
+        assertNull(plainSchemaDAO.find("aLong", UPlainSchema.class));
+
+        plainSchemaDAO.flush();
+
+        assertEquals(5, resourceDAO.find("resource-db-sync").getUmapping().getItems().size());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ReportTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ReportTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ReportTest.java
new file mode 100644
index 0000000..55481cd
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ReportTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.Date;
+import javax.persistence.EntityExistsException;
+import org.apache.syncope.common.lib.types.ReportExecStatus;
+import org.apache.syncope.persistence.api.dao.ReportDAO;
+import org.apache.syncope.persistence.api.dao.ReportExecDAO;
+import org.apache.syncope.persistence.api.entity.Report;
+import org.apache.syncope.persistence.api.entity.ReportExec;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.JPAReport;
+import org.apache.syncope.persistence.jpa.entity.JPAReportExec;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class ReportTest extends AbstractTest {
+
+    @Autowired
+    private ReportDAO reportDAO;
+
+    @Autowired
+    private ReportExecDAO reportExecDAO;
+
+    @Test
+    public void find() {
+        Report report = reportDAO.find(1L);
+        assertNotNull(report);
+
+        assertNotNull(report.getExecs());
+        assertFalse(report.getExecs().isEmpty());
+        assertEquals(1, report.getExecs().size());
+    }
+
+    @Test(expected = EntityExistsException.class)
+    public void saveWithExistingName() {
+        Report report = reportDAO.find(1L);
+        assertNotNull(report);
+
+        String name = report.getName();
+
+        report = new JPAReport();
+        report.setName(name);
+
+        reportDAO.save(report);
+        reportDAO.flush();
+    }
+
+    @Test
+    public void save() {
+        Report report = reportDAO.find(1L);
+        assertNotNull(report);
+        assertEquals(1, report.getExecs().size());
+
+        ReportExec reportExec = new JPAReportExec();
+        reportExec.setReport(report);
+        reportExec.setStartDate(new Date());
+        reportExec.setEndDate(new Date());
+        reportExec.setStatus(ReportExecStatus.SUCCESS);
+
+        report.addExec(reportExec);
+
+        reportExec = reportExecDAO.save(reportExec);
+        assertNotNull(reportExec);
+        assertNotNull(reportExec.getKey());
+
+        reportExecDAO.flush();
+
+        report = reportDAO.find(1L);
+        assertNotNull(report);
+        assertEquals(2, report.getExecs().size());
+    }
+
+    @Test
+    public void deleteReport() {
+        reportDAO.delete(1L);
+
+        reportDAO.flush();
+
+        assertNull(reportDAO.find(1L));
+        assertNull(reportExecDAO.find(1L));
+    }
+
+    @Test
+    public void deleteReportExecution() {
+        ReportExec execution = reportExecDAO.find(1L);
+        int executionNumber = execution.getReport().getExecs().size();
+
+        reportExecDAO.delete(1L);
+
+        reportExecDAO.flush();
+
+        assertNull(reportExecDAO.find(1L));
+
+        Report report = reportDAO.find(1L);
+        assertEquals(report.getExecs().size(), executionNumber - 1);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ResourceTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ResourceTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ResourceTest.java
new file mode 100644
index 0000000..a78aeee
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/ResourceTest.java
@@ -0,0 +1,298 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.EntityManager;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.dao.ConnInstanceDAO;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.dao.PolicyDAO;
+import org.apache.syncope.persistence.api.dao.TaskDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.persistence.api.entity.role.RMappingItem;
+import org.apache.syncope.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.persistence.api.entity.user.UMapping;
+import org.apache.syncope.persistence.api.entity.user.UMappingItem;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.JPAExternalResource;
+import org.apache.syncope.persistence.jpa.entity.role.JPARMappingItem;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUMapping;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUMappingItem;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class ResourceTest extends AbstractTest {
+
+    @Autowired
+    private EntityManager entityManager;
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    @Autowired
+    private ConnInstanceDAO connInstanceDAO;
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private TaskDAO taskDAO;
+
+    @Autowired
+    private PolicyDAO policyDAO;
+
+    @Test
+    public void createWithPasswordPolicy() {
+        final String resourceName = "resourceWithPasswordPolicy";
+
+        PasswordPolicy policy = (PasswordPolicy) policyDAO.find(4L);
+        ExternalResource resource = new JPAExternalResource();
+        resource.setKey(resourceName);
+        resource.setPasswordPolicy(policy);
+
+        ConnInstance connector = connInstanceDAO.find(100L);
+        assertNotNull("connector not found", connector);
+        resource.setConnector(connector);
+
+        ExternalResource actual = resourceDAO.save(resource);
+        assertNotNull(actual);
+
+        actual = resourceDAO.find(actual.getKey());
+        assertNotNull(actual);
+        assertNotNull(actual.getPasswordPolicy());
+
+        resourceDAO.delete(resourceName);
+        assertNull(resourceDAO.find(resourceName));
+
+        assertNotNull(policyDAO.find(4L));
+    }
+
+    @Test
+    public void save() {
+        ExternalResource resource = new JPAExternalResource();
+        resource.setKey("ws-target-resource-save");
+
+        // specify the connector
+        ConnInstance connector = connInstanceDAO.find(100L);
+        assertNotNull("connector not found", connector);
+
+        resource.setConnector(connector);
+
+        UMapping mapping = new JPAUMapping();
+        mapping.setResource(resource);
+        resource.setUmapping(mapping);
+
+        // specify mappings
+        for (int i = 0; i < 3; i++) {
+            UMappingItem item = new JPAUMappingItem();
+            item.setExtAttrName("test" + i);
+            item.setIntAttrName("nonexistent" + i);
+            item.setIntMappingType(IntMappingType.UserSchema);
+            item.setMandatoryCondition("false");
+            item.setPurpose(MappingPurpose.SYNCHRONIZATION);
+            mapping.addItem(item);
+            item.setMapping(mapping);
+        }
+        UMappingItem accountId = new JPAUMappingItem();
+        accountId.setExtAttrName("username");
+        accountId.setIntAttrName("username");
+        accountId.setIntMappingType(IntMappingType.UserId);
+        accountId.setPurpose(MappingPurpose.PROPAGATION);
+        mapping.setAccountIdItem(accountId);
+        accountId.setMapping(mapping);
+
+        // map a derived attribute
+        UMappingItem derived = new JPAUMappingItem();
+        derived.setAccountid(false);
+        derived.setExtAttrName("fullname");
+        derived.setIntAttrName("cn");
+        derived.setIntMappingType(IntMappingType.UserDerivedSchema);
+        derived.setPurpose(MappingPurpose.PROPAGATION);
+        mapping.addItem(derived);
+        derived.setMapping(mapping);
+
+        // save the resource
+        ExternalResource actual = resourceDAO.save(resource);
+        assertNotNull(actual);
+        assertNotNull(actual.getUmapping());
+
+        resourceDAO.flush();
+        resourceDAO.detach(actual);
+        connInstanceDAO.detach(connector);
+
+        // assign the new resource to an user
+        User user = userDAO.find(1L);
+        assertNotNull("user not found", user);
+
+        user.addResource(actual);
+
+        resourceDAO.flush();
+
+        // retrieve resource
+        resource = resourceDAO.find(actual.getKey());
+        assertNotNull(resource);
+
+        // check connector
+        connector = connInstanceDAO.find(100L);
+        assertNotNull(connector);
+
+        assertNotNull(connector.getResources());
+        assertTrue(connector.getResources().contains(resource));
+
+        assertNotNull(resource.getConnector());
+        assertTrue(resource.getConnector().equals(connector));
+
+        // check mappings
+        List<? extends UMappingItem> items = resource.getUmapping().getItems();
+        assertNotNull(items);
+        assertEquals(5, items.size());
+
+        // check user
+        user = userDAO.find(1L);
+        assertNotNull(user);
+        assertNotNull(user.getResources());
+        assertTrue(user.getResources().contains(actual));
+    }
+
+    @Test
+    public void delete() {
+        ExternalResource resource = resourceDAO.find("ws-target-resource-2");
+        assertNotNull("find to delete did not work", resource);
+
+        // -------------------------------------
+        // Get originally associated connector
+        // -------------------------------------
+        ConnInstance connector = resource.getConnector();
+        assertNotNull(connector);
+
+        Long connectorId = connector.getKey();
+        // -------------------------------------
+
+        // -------------------------------------
+        // Get originally associated users
+        // -------------------------------------
+        List<User> users = userDAO.findByResource(resource);
+        assertNotNull(users);
+
+        Set<Long> userIds = new HashSet<Long>();
+        for (User user : users) {
+            userIds.add(user.getKey());
+        }
+        // -------------------------------------
+
+        // Get tasks
+        List<PropagationTask> propagationTasks = taskDAO.findAll(resource, TaskType.PROPAGATION);
+        assertFalse(propagationTasks.isEmpty());
+
+        // delete resource
+        resourceDAO.delete(resource.getKey());
+
+        // close the transaction
+        resourceDAO.flush();
+
+        // resource must be removed
+        ExternalResource actual = resourceDAO.find("ws-target-resource-2");
+        assertNull("delete did not work", actual);
+
+        // resource must be not referenced any more from users
+        for (Long id : userIds) {
+            User actualUser = userDAO.find(id);
+            assertNotNull(actualUser);
+            for (ExternalResource res : actualUser.getResources()) {
+                assertFalse(res.getKey().equalsIgnoreCase(resource.getKey()));
+            }
+        }
+
+        // resource must be not referenced any more from the connector
+        ConnInstance actualConnector = connInstanceDAO.find(connectorId);
+        assertNotNull(actualConnector);
+        for (ExternalResource res : actualConnector.getResources()) {
+            assertFalse(res.getKey().equalsIgnoreCase(resource.getKey()));
+        }
+
+        // there must be no tasks
+        for (PropagationTask task : propagationTasks) {
+            assertNull(taskDAO.find(task.getKey()));
+        }
+    }
+
+    @Test
+    public void emptyMapping() {
+        ExternalResource ldap = resourceDAO.find("resource-ldap");
+        assertNotNull(ldap);
+        assertNotNull(ldap.getUmapping());
+        assertNotNull(ldap.getRmapping());
+
+        List<? extends RMappingItem> items = ldap.getRmapping().getItems();
+        assertNotNull(items);
+        assertFalse(items.isEmpty());
+        List<Long> itemIds = new ArrayList<Long>(items.size());
+        for (RMappingItem item : items) {
+            itemIds.add(item.getKey());
+        }
+
+        ldap.setRmapping(null);
+
+        resourceDAO.save(ldap);
+        resourceDAO.flush();
+
+        for (Long itemId : itemIds) {
+            assertNull(entityManager.find(JPARMappingItem.class, itemId));
+        }
+    }
+
+    @Test
+    public void issue243() {
+        ExternalResource csv = resourceDAO.find("resource-csv");
+        assertNotNull(csv);
+
+        int origMapItems = csv.getUmapping().getItems().size();
+
+        UMappingItem newMapItem = new JPAUMappingItem();
+        newMapItem.setIntMappingType(IntMappingType.Username);
+        newMapItem.setExtAttrName("TEST");
+        newMapItem.setPurpose(MappingPurpose.PROPAGATION);
+        csv.getUmapping().addItem(newMapItem);
+
+        resourceDAO.save(csv);
+        resourceDAO.flush();
+
+        csv = resourceDAO.find("resource-csv");
+        assertNotNull(csv);
+        assertEquals(origMapItems + 1, csv.getUmapping().getItems().size());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/RoleTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/RoleTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/RoleTest.java
new file mode 100644
index 0000000..5ae1ff5
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/RoleTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.persistence.api.dao.PlainAttrDAO;
+import org.apache.syncope.persistence.api.dao.PlainAttrValueDAO;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.dao.PolicyDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttr;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.role.RPlainSchema;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.role.JPARole;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class RoleTest extends AbstractTest {
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    @Autowired
+    private PlainAttrDAO plainAttrDAO;
+
+    @Autowired
+    private PlainAttrValueDAO plainAttrValueDAO;
+
+    @Autowired
+    private EntitlementDAO entitlementDAO;
+
+    @Autowired
+    private PolicyDAO policyDAO;
+
+    @Test(expected = InvalidEntityException.class)
+    public void saveWithTwoOwners() {
+        Role root = roleDAO.find("root", null);
+        assertNotNull("did not find expected role", root);
+
+        User user = userDAO.find(1L);
+        assertNotNull("did not find expected user", user);
+
+        Role role = new JPARole();
+        role.setName("error");
+        role.setUserOwner(user);
+        role.setRoleOwner(root);
+
+        roleDAO.save(role);
+    }
+
+    @Test
+    public void findByOwner() {
+        Role role = roleDAO.find(6L);
+        assertNotNull("did not find expected role", role);
+
+        User user = userDAO.find(5L);
+        assertNotNull("did not find expected user", user);
+
+        assertEquals(user, role.getUserOwner());
+
+        Role child1 = roleDAO.find(7L);
+        assertNotNull(child1);
+        assertEquals(role, child1.getParent());
+
+        Role child2 = roleDAO.find(10L);
+        assertNotNull(child2);
+        assertEquals(role, child2.getParent());
+
+        List<Role> ownedRoles = roleDAO.findOwnedByUser(user.getKey());
+        assertFalse(ownedRoles.isEmpty());
+        assertEquals(2, ownedRoles.size());
+        assertTrue(ownedRoles.contains(role));
+        assertTrue(ownedRoles.contains(child1));
+        assertFalse(ownedRoles.contains(child2));
+    }
+
+    public void createWithPasswordPolicy() {
+        PasswordPolicy policy = (PasswordPolicy) policyDAO.find(4L);
+        Role role = new JPARole();
+        role.setName("roleWithPasswordPolicy");
+        role.setPasswordPolicy(policy);
+
+        Role actual = roleDAO.save(role);
+        assertNotNull(actual);
+
+        actual = roleDAO.find(actual.getKey());
+        assertNotNull(actual);
+        assertNotNull(actual.getPasswordPolicy());
+
+        roleDAO.delete(actual.getKey());
+        assertNull(roleDAO.find(actual.getKey()));
+
+        assertNotNull(policyDAO.find(4L));
+    }
+
+    @Test
+    public void delete() {
+        roleDAO.delete(2L);
+
+        roleDAO.flush();
+
+        assertNull(roleDAO.find(2L));
+        assertEquals(1, roleDAO.findByEntitlement(entitlementDAO.find("base")).size());
+        assertEquals(userDAO.find(2L).getRoles().size(), 2);
+        assertNull(plainAttrDAO.find(700L, RPlainAttr.class));
+        assertNull(plainAttrValueDAO.find(41L, RPlainAttrValue.class));
+        assertNotNull(plainSchemaDAO.find("icon", RPlainSchema.class));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab462f08/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/SecurityQuestionTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/SecurityQuestionTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/SecurityQuestionTest.java
new file mode 100644
index 0000000..8fcac93
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/SecurityQuestionTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.syncope.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertNull;
+
+import org.apache.syncope.persistence.api.dao.SecurityQuestionDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class SecurityQuestionTest extends AbstractTest {
+
+    @Autowired
+    private SecurityQuestionDAO securityQuestionDAO;
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Test
+    public void test() {
+        User user = userDAO.find(4L);
+
+        user.setSecurityQuestion(securityQuestionDAO.find(1L));
+        user.setSecurityAnswer("Rossi");
+        userDAO.save(user);
+
+        userDAO.flush();
+
+        securityQuestionDAO.delete(1L);
+
+        userDAO.flush();
+
+        user = userDAO.find(4L);
+
+        assertNull(user.getSecurityQuestion());
+    }
+}