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 2014/06/26 11:56:06 UTC

svn commit: r1605721 - in /syncope/trunk: client/src/main/java/org/apache/syncope/client/ common/src/main/java/org/apache/syncope/common/types/ console/src/main/java/org/apache/syncope/console/ console/src/main/java/org/apache/syncope/console/commons/ ...

Author: ilgrosso
Date: Thu Jun 26 09:56:06 2014
New Revision: 1605721

URL: http://svn.apache.org/r1605721
Log:
[SYNCOPE-517] Client REST calls for users and roles now feature ETag (when applicable)

Added:
    syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/AbstractSubjectRestClient.java
      - copied, changed from r1605679, syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/AbstractAttributableRestClient.java
Removed:
    syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/AbstractAttributableRestClient.java
Modified:
    syncope/trunk/client/src/main/java/org/apache/syncope/client/SyncopeClient.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/types/ClientExceptionType.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/SyncopeSession.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/AttributableDataProvider.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/status/StatusUtils.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/RoleModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/StatusModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AbstractSearchResultPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleSearchResultPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleTabPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/UserSearchResultPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/BaseRestClient.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/RoleRestClient.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserRestClient.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/utils/RestServiceExceptionMapper.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/services/AbstractServiceImpl.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/services/RoleServiceImpl.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserSelfServiceImpl.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserServiceImpl.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java

Modified: syncope/trunk/client/src/main/java/org/apache/syncope/client/SyncopeClient.java
URL: http://svn.apache.org/viewvc/syncope/trunk/client/src/main/java/org/apache/syncope/client/SyncopeClient.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/client/src/main/java/org/apache/syncope/client/SyncopeClient.java (original)
+++ syncope/trunk/client/src/main/java/org/apache/syncope/client/SyncopeClient.java Thu Jun 26 09:56:06 2014
@@ -245,11 +245,11 @@ public class SyncopeClient {
     }
 
     /**
-     * Fetches <tt>Etag</tt> header value from latest service run (if available).
+     * Fetches <tt>ETag</tt> header value from latest service run (if available).
      *
      * @param <T> any service class
      * @param service service class instance
-     * @return <tt>Etag</tt> header value from latest service run (if available)
+     * @return <tt>ETag</tt> header value from latest service run (if available)
      */
     public <T> EntityTag getLatestEntityTag(final T service) {
         return WebClient.client(service).getResponse().getEntityTag();

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/types/ClientExceptionType.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/types/ClientExceptionType.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/types/ClientExceptionType.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/types/ClientExceptionType.java Thu Jun 26 09:56:06 2014
@@ -24,6 +24,7 @@ public enum ClientExceptionType {
 
     AssociatedResources(Response.Status.BAD_REQUEST),
     Composite(Response.Status.BAD_REQUEST),
+    ConcurrentModification(Response.Status.PRECONDITION_FAILED),
     DataIntegrityViolation(Response.Status.BAD_REQUEST),
     EntityExists(Response.Status.CONFLICT),
     GenericPersistence(Response.Status.BAD_REQUEST),

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/SyncopeSession.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/SyncopeSession.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/SyncopeSession.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/SyncopeSession.java Thu Jun 26 09:56:06 2014
@@ -20,12 +20,15 @@ package org.apache.syncope.console;
 
 import java.text.DateFormat;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import javax.ws.rs.core.EntityTag;
 import javax.ws.rs.core.MediaType;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.SyncopeClient;
 import org.apache.syncope.client.SyncopeClientFactoryBean;
 import org.apache.syncope.common.types.SubjectType;
@@ -61,7 +64,8 @@ public class SyncopeSession extends WebS
 
     private final String anonymousKey;
 
-    private final Map<Integer, SyncopeClient> clients = new HashMap<Integer, SyncopeClient>();
+    private final Map<Integer, SyncopeClient> clients =
+            Collections.synchronizedMap(new HashMap<Integer, SyncopeClient>());
 
     public static SyncopeSession get() {
         return (SyncopeSession) Session.get();
@@ -101,12 +105,28 @@ public class SyncopeSession extends WebS
         return getService(service, this.username, this.password);
     }
 
+    public <T> T getService(final String etag, final Class<T> service) {
+        T serviceInstance = getService(service, this.username, this.password);
+        WebClient.client(serviceInstance).match(new EntityTag(etag), false);
+
+        return serviceInstance;
+    }
+
+    public <T> void resetClient(final Class<T> service) {
+        T serviceInstance = getService(service, this.username, this.password);
+        WebClient.client(serviceInstance).reset();
+    }
+
     public <T> T getService(final MediaType mediaType, final Class<T> serviceClass) {
-        SyncopeClientFactoryBean.ContentType preType = clientFactory.getContentType();
+        T service;
+
+        synchronized (clientFactory) {
+            SyncopeClientFactoryBean.ContentType preType = clientFactory.getContentType();
 
-        clientFactory.setContentType(SyncopeClientFactoryBean.ContentType.fromString(mediaType.toString()));
-        T service = clientFactory.create(username, password).getService(serviceClass);
-        clientFactory.setContentType(preType);
+            clientFactory.setContentType(SyncopeClientFactoryBean.ContentType.fromString(mediaType.toString()));
+            service = clientFactory.create(username, password).getService(serviceClass);
+            clientFactory.setContentType(preType);
+        }
 
         return service;
     }
@@ -116,10 +136,7 @@ public class SyncopeSession extends WebS
     }
 
     public <T> T getService(final Class<T> serviceClass, final String username, final String password) {
-        final int clientKey = new HashCodeBuilder().
-                append(username).
-                append(password).
-                toHashCode();
+        final int clientKey = new HashCodeBuilder().append(username).append(password).toHashCode();
 
         if (!clients.containsKey(clientKey)) {
             clients.put(clientKey, clientFactory.create(username, password));

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/AttributableDataProvider.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/AttributableDataProvider.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/AttributableDataProvider.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/AttributableDataProvider.java Thu Jun 26 09:56:06 2014
@@ -22,7 +22,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import org.apache.syncope.common.to.AbstractAttributableTO;
-import org.apache.syncope.console.rest.AbstractAttributableRestClient;
+import org.apache.syncope.console.rest.AbstractSubjectRestClient;
 import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
 import org.apache.wicket.model.CompoundPropertyModel;
@@ -44,9 +44,9 @@ public class AttributableDataProvider ex
 
     private final boolean filtered;
 
-    private final AbstractAttributableRestClient restClient;
+    private final AbstractSubjectRestClient restClient;
 
-    public AttributableDataProvider(final AbstractAttributableRestClient restClient,
+    public AttributableDataProvider(final AbstractSubjectRestClient restClient,
             final int paginatorRows, final boolean filtered) {
 
         super();

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/status/StatusUtils.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/status/StatusUtils.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/status/StatusUtils.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/status/StatusUtils.java Thu Jun 26 09:56:06 2014
@@ -34,7 +34,7 @@ import org.apache.syncope.console.common
 import org.apache.syncope.console.commons.Constants;
 import org.apache.syncope.console.pages.panels.ImagePanel;
 import org.apache.syncope.console.pages.panels.StatusPanel;
-import org.apache.syncope.console.rest.AbstractAttributableRestClient;
+import org.apache.syncope.console.rest.AbstractSubjectRestClient;
 import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.behavior.Behavior;
@@ -54,9 +54,9 @@ public class StatusUtils implements Seri
 
     public static final String IMG_STATUES = "../statuses/";
 
-    private final AbstractAttributableRestClient restClient;
+    private final AbstractSubjectRestClient restClient;
 
-    public StatusUtils(final AbstractAttributableRestClient restClient) {
+    public StatusUtils(final AbstractSubjectRestClient restClient) {
         this.restClient = restClient;
     }
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java Thu Jun 26 09:56:06 2014
@@ -91,7 +91,7 @@ public class EditUserModalPage extends U
 
             // update user just if it is changed
             if (!userMod.isEmpty()) {
-                userTO = userRestClient.update(userMod);
+                userTO = userRestClient.update(initialUserTO.getETagValue(), userMod);
             }
         }
     }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/RoleModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/RoleModalPage.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/RoleModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/RoleModalPage.java Thu Jun 26 09:56:06 2014
@@ -157,7 +157,7 @@ public class RoleModalPage extends BaseM
             if (roleMod.isEmpty()) {
                 result = roleTO;
             } else {
-                result = roleRestClient.update(roleMod);
+                result = roleRestClient.update(originalRoleTO.getETagValue(), roleMod);
             }
         }
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/StatusModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/StatusModalPage.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/StatusModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/StatusModalPage.java Thu Jun 26 09:56:06 2014
@@ -260,7 +260,9 @@ public class StatusModalPage<T extends A
                 public void onClick(final AjaxRequestTarget target) {
                     try {
                         userRestClient.reactivate(
-                                subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                subjectTO.getETagValue(),
+                                subjectTO.getId(),
+                                new ArrayList<StatusBean>(table.getModelObject()));
 
                         ((BasePage) pageRef.getPage()).setModalResult(true);
 
@@ -281,7 +283,9 @@ public class StatusModalPage<T extends A
                 public void onClick(final AjaxRequestTarget target) {
                     try {
                         userRestClient.suspend(
-                                subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                subjectTO.getETagValue(),
+                                subjectTO.getId(),
+                                new ArrayList<StatusBean>(table.getModelObject()));
 
                         if (pageRef.getPage() instanceof BasePage) {
                             ((BasePage) pageRef.getPage()).setModalResult(true);
@@ -305,10 +309,14 @@ public class StatusModalPage<T extends A
                     try {
                         if (subjectTO instanceof UserTO) {
                             userRestClient.unlink(
-                                    subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                    subjectTO.getETagValue(),
+                                    subjectTO.getId(),
+                                    new ArrayList<StatusBean>(table.getModelObject()));
                         } else {
                             roleRestClient.unlink(
-                                    subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                    subjectTO.getETagValue(),
+                                    subjectTO.getId(),
+                                    new ArrayList<StatusBean>(table.getModelObject()));
                         }
 
                         ((BasePage) pageRef.getPage()).setModalResult(true);
@@ -330,10 +338,14 @@ public class StatusModalPage<T extends A
                     try {
                         if (subjectTO instanceof UserTO) {
                             userRestClient.link(
-                                    subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                    subjectTO.getETagValue(),
+                                    subjectTO.getId(),
+                                    new ArrayList<StatusBean>(table.getModelObject()));
                         } else {
                             roleRestClient.link(
-                                    subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                    subjectTO.getETagValue(),
+                                    subjectTO.getId(),
+                                    new ArrayList<StatusBean>(table.getModelObject()));
                         }
 
                         ((BasePage) pageRef.getPage()).setModalResult(true);
@@ -353,13 +365,17 @@ public class StatusModalPage<T extends A
                 @Override
                 public void onClick(final AjaxRequestTarget target) {
                     try {
-                        final BulkActionResult bulkActionResult;
+                        BulkActionResult bulkActionResult;
                         if (subjectTO instanceof UserTO) {
                             bulkActionResult = userRestClient.deprovision(
-                                    subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                    subjectTO.getETagValue(),
+                                    subjectTO.getId(),
+                                    new ArrayList<StatusBean>(table.getModelObject()));
                         } else {
                             bulkActionResult = roleRestClient.deprovision(
-                                    subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                    subjectTO.getETagValue(),
+                                    subjectTO.getId(),
+                                    new ArrayList<StatusBean>(table.getModelObject()));
                         }
 
                         ((BasePage) pageRef.getPage()).setModalResult(true);
@@ -385,7 +401,9 @@ public class StatusModalPage<T extends A
                     } else {
                         try {
                             final BulkActionResult bulkActionResult = roleRestClient.provision(
-                                    subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                    subjectTO.getETagValue(),
+                                    subjectTO.getId(),
+                                    new ArrayList<StatusBean>(table.getModelObject()));
 
                             ((BasePage) pageRef.getPage()).setModalResult(true);
                             loadBulkActionResultPage(table.getModelObject(), bulkActionResult);
@@ -408,10 +426,14 @@ public class StatusModalPage<T extends A
                         final BulkActionResult bulkActionResult;
                         if (subjectTO instanceof UserTO) {
                             bulkActionResult = userRestClient.unassign(
-                                    subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                    subjectTO.getETagValue(),
+                                    subjectTO.getId(),
+                                    new ArrayList<StatusBean>(table.getModelObject()));
                         } else {
                             bulkActionResult = roleRestClient.unassign(
-                                    subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                    subjectTO.getETagValue(),
+                                    subjectTO.getId(),
+                                    new ArrayList<StatusBean>(table.getModelObject()));
                         }
 
                         ((BasePage) pageRef.getPage()).setModalResult(true);
@@ -436,7 +458,9 @@ public class StatusModalPage<T extends A
                     } else {
                         try {
                             final BulkActionResult bulkActionResult = roleRestClient.assign(
-                                    subjectTO.getId(), new ArrayList<StatusBean>(table.getModelObject()));
+                                    subjectTO.getETagValue(),
+                                    subjectTO.getId(),
+                                    new ArrayList<StatusBean>(table.getModelObject()));
 
                             ((BasePage) pageRef.getPage()).setModalResult(true);
                             loadBulkActionResultPage(table.getModelObject(), bulkActionResult);
@@ -540,6 +564,7 @@ public class StatusModalPage<T extends A
                             switch (type) {
                                 case ASSIGN:
                                     bulkActionResult = userRestClient.assign(
+                                            subjectTO.getETagValue(),
                                             subjectTO.getId(),
                                             new ArrayList<StatusBean>(selection),
                                             changepwd.getModelObject(),
@@ -547,6 +572,7 @@ public class StatusModalPage<T extends A
                                     break;
                                 case PROVISION:
                                     bulkActionResult = userRestClient.provision(
+                                            subjectTO.getETagValue(),
                                             subjectTO.getId(),
                                             new ArrayList<StatusBean>(selection),
                                             changepwd.getModelObject(),

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AbstractSearchResultPanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AbstractSearchResultPanel.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AbstractSearchResultPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AbstractSearchResultPanel.java Thu Jun 26 09:56:06 2014
@@ -26,7 +26,7 @@ import org.apache.syncope.console.common
 import org.apache.syncope.console.commons.PreferenceManager;
 import org.apache.syncope.console.commons.XMLRolesReader;
 import org.apache.syncope.console.pages.AbstractBasePage;
-import org.apache.syncope.console.rest.AbstractAttributableRestClient;
+import org.apache.syncope.console.rest.AbstractSubjectRestClient;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -96,7 +96,7 @@ public abstract class AbstractSearchResu
     @SpringBean
     protected XMLRolesReader xmlRolesReader;
 
-    protected final AbstractAttributableRestClient restClient;
+    protected final AbstractSubjectRestClient restClient;
 
     /**
      * Number of rows per page.
@@ -155,7 +155,7 @@ public abstract class AbstractSearchResu
     protected final AbstractBasePage page;
 
     protected <T extends AbstractAttributableTO> AbstractSearchResultPanel(final String id, final boolean filtered,
-            final String fiql, final PageReference pageRef, final AbstractAttributableRestClient restClient) {
+            final String fiql, final PageReference pageRef, final AbstractSubjectRestClient restClient) {
 
         super(id);
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleSearchResultPanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleSearchResultPanel.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleSearchResultPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleSearchResultPanel.java Thu Jun 26 09:56:06 2014
@@ -29,7 +29,7 @@ import org.apache.syncope.console.common
 import org.apache.syncope.console.pages.ResultStatusModalPage;
 import org.apache.syncope.console.pages.RoleModalPage;
 import org.apache.syncope.console.pages.StatusModalPage;
-import org.apache.syncope.console.rest.AbstractAttributableRestClient;
+import org.apache.syncope.console.rest.AbstractSubjectRestClient;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLink.ActionType;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
@@ -52,7 +52,7 @@ public class RoleSearchResultPanel exten
     private final static String PAGEID = "Roles";
 
     public <T extends AbstractAttributableTO> RoleSearchResultPanel(final String id, final boolean filtered,
-            final String fiql, final PageReference callerRef, final AbstractAttributableRestClient restClient) {
+            final String fiql, final PageReference callerRef, final AbstractSubjectRestClient restClient) {
 
         super(id, filtered, fiql, callerRef, restClient);
         initResultTable();
@@ -133,7 +133,8 @@ public class RoleSearchResultPanel exten
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         try {
-                            final RoleTO roleTO = (RoleTO) restClient.delete(model.getObject().getId());
+                            final RoleTO roleTO = (RoleTO) restClient.
+                                    delete(model.getObject().getETagValue(), model.getObject().getId());
 
                             page.setModalResult(true);
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleTabPanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleTabPanel.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleTabPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleTabPanel.java Thu Jun 26 09:56:06 2014
@@ -138,7 +138,7 @@ public class RoleTabPanel extends Panel 
             @Override
             public void onClick(final AjaxRequestTarget target) {
                 try {
-                    final RoleTO roleTO = roleRestClient.delete(selectedNode.getId());
+                    final RoleTO roleTO = roleRestClient.delete(selectedNode.getETagValue(), selectedNode.getId());
 
                     ((Roles) pageRef.getPage()).setModalResult(true);
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/UserSearchResultPanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/UserSearchResultPanel.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/UserSearchResultPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/UserSearchResultPanel.java Thu Jun 26 09:56:06 2014
@@ -34,7 +34,7 @@ import org.apache.syncope.console.pages.
 import org.apache.syncope.console.pages.EditUserModalPage;
 import org.apache.syncope.console.pages.ResultStatusModalPage;
 import org.apache.syncope.console.pages.StatusModalPage;
-import org.apache.syncope.console.rest.AbstractAttributableRestClient;
+import org.apache.syncope.console.rest.AbstractSubjectRestClient;
 import org.apache.syncope.console.rest.SchemaRestClient;
 import org.apache.syncope.console.rest.UserRestClient;
 import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
@@ -72,7 +72,7 @@ public class UserSearchResultPanel exten
     private final List<String> vSchemaNames;
 
     public <T extends AbstractAttributableTO> UserSearchResultPanel(final String id, final boolean filtered,
-            final String fiql, final PageReference callerRef, final AbstractAttributableRestClient restClient) {
+            final String fiql, final PageReference callerRef, final AbstractSubjectRestClient restClient) {
 
         super(id, filtered, fiql, callerRef, restClient);
 
@@ -210,7 +210,8 @@ public class UserSearchResultPanel exten
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         try {
-                            final UserTO userTO = (UserTO) restClient.delete(model.getObject().getId());
+                            final UserTO userTO = (UserTO) restClient.
+                                    delete(model.getObject().getETagValue(), model.getObject().getId());
 
                             page.setModalResult(true);
 

Copied: syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/AbstractSubjectRestClient.java (from r1605679, syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/AbstractAttributableRestClient.java)
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/AbstractSubjectRestClient.java?p2=syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/AbstractSubjectRestClient.java&p1=syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/AbstractAttributableRestClient.java&r1=1605679&r2=1605721&rev=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/AbstractAttributableRestClient.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/AbstractSubjectRestClient.java Thu Jun 26 09:56:06 2014
@@ -25,7 +25,7 @@ import org.apache.syncope.common.reqres.
 import org.apache.syncope.common.to.ConnObjectTO;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 
-public abstract class AbstractAttributableRestClient extends BaseRestClient {
+public abstract class AbstractSubjectRestClient extends BaseRestClient {
 
     private static final long serialVersionUID = 1962529678091410544L;
 
@@ -40,7 +40,7 @@ public abstract class AbstractAttributab
 
     public abstract ConnObjectTO getConnectorObject(String resourceName, Long id);
 
-    public abstract AbstractAttributableTO delete(Long id);
+    public abstract AbstractAttributableTO delete(String etag, Long id);
 
-    public abstract BulkActionResult bulkAction(BulkAction action);
+    public abstract void bulkAction(BulkAction action);
 }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/BaseRestClient.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/BaseRestClient.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/BaseRestClient.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/BaseRestClient.java Thu Jun 26 09:56:06 2014
@@ -44,6 +44,14 @@ public abstract class BaseRestClient imp
         return SyncopeSession.get().getService(serviceClass);
     }
 
+    protected <T> T getService(final String etag, final Class<T> serviceClass) {
+        return SyncopeSession.get().getService(etag, serviceClass);
+    }
+
+    protected <T> void resetClient(final Class<T> serviceClass) {
+        SyncopeSession.get().resetClient(serviceClass);
+    }
+
     protected String toOrderBy(final SortParam<String> sort) {
         OrderByClauseBuilder builder = SyncopeClient.getOrderByClauseBuilder();
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/RoleRestClient.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/RoleRestClient.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/RoleRestClient.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/RoleRestClient.java Thu Jun 26 09:56:06 2014
@@ -43,7 +43,7 @@ import org.springframework.stereotype.Co
  * Console client for invoking Rest Role's services.
  */
 @Component
-public class RoleRestClient extends AbstractAttributableRestClient {
+public class RoleRestClient extends AbstractSubjectRestClient {
 
     private static final long serialVersionUID = -8549081557283519638L;
 
@@ -85,53 +85,101 @@ public class RoleRestClient extends Abst
         return getAnonymousService(RoleService.class).read(id);
     }
 
-    public RoleTO update(final RoleMod roleMod) {
-        return getService(RoleService.class).update(roleMod.getId(), roleMod).readEntity(RoleTO.class);
-    }
-
-    @Override
-    public RoleTO delete(final Long id) {
-        return getService(RoleService.class).delete(id).readEntity(RoleTO.class);
-    }
-
-    @Override
-    public BulkActionResult bulkAction(final BulkAction action) {
-        return getService(RoleRestClient.class).bulkAction(action);
-    }
-
-    public BulkActionResult unlink(final long roleId, final List<StatusBean> statuses) {
-        return getService(RoleService.class).bulkDeassociation(roleId, ResourceDeassociationActionType.UNLINK,
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class)).
-                readEntity(BulkActionResult.class);
-    }
-
-    public BulkActionResult link(final long roleId, final List<StatusBean> statuses) {
-        return getService(RoleService.class).bulkAssociation(roleId, ResourceAssociationActionType.LINK,
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class)).
-                readEntity(BulkActionResult.class);
-    }
-
-    public BulkActionResult deprovision(final long roleId, final List<StatusBean> statuses) {
-        return getService(RoleService.class).bulkDeassociation(roleId, ResourceDeassociationActionType.DEPROVISION,
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class)).
-                readEntity(BulkActionResult.class);
-    }
-
-    public BulkActionResult provision(final long roleId, final List<StatusBean> statuses) {
-        return getService(RoleService.class).bulkAssociation(roleId, ResourceAssociationActionType.PROVISION,
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class)).
-                readEntity(BulkActionResult.class);
-    }
-
-    public BulkActionResult unassign(final long roleId, final List<StatusBean> statuses) {
-        return getService(RoleService.class).bulkDeassociation(roleId, ResourceDeassociationActionType.UNASSIGN,
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class)).
-                readEntity(BulkActionResult.class);
-    }
-
-    public BulkActionResult assign(final long roleId, final List<StatusBean> statuses) {
-        return getService(RoleService.class).bulkAssociation(roleId, ResourceAssociationActionType.ASSIGN,
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class)).
-                readEntity(BulkActionResult.class);
+    public RoleTO update(final String etag, final RoleMod roleMod) {
+        RoleTO result;
+        synchronized (this) {
+            RoleService service = getService(etag, RoleService.class);
+            result = service.update(roleMod.getId(), roleMod).readEntity(RoleTO.class);
+            resetClient(RoleService.class);
+        }
+        return result;
+    }
+
+    @Override
+    public RoleTO delete(final String etag, final Long id) {
+        RoleTO result;
+        synchronized (this) {
+            RoleService service = getService(etag, RoleService.class);
+            result = service.delete(id).readEntity(RoleTO.class);
+            resetClient(RoleService.class);
+        }
+        return result;
+    }
+
+    @Override
+    public void bulkAction(final BulkAction action) {
+        getService(RoleRestClient.class).bulkAction(action);
+    }
+
+    public void unlink(final String etag, final long roleId, final List<StatusBean> statuses) {
+        synchronized (this) {
+            RoleService service = getService(etag, RoleService.class);
+            service.bulkDeassociation(roleId, ResourceDeassociationActionType.UNLINK,
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class));
+            resetClient(RoleService.class);
+        }
+    }
+
+    public void link(final String etag, final long roleId, final List<StatusBean> statuses) {
+        synchronized (this) {
+            RoleService service = getService(etag, RoleService.class);
+            service.bulkAssociation(roleId, ResourceAssociationActionType.LINK,
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class));
+            resetClient(RoleService.class);
+        }
+    }
+
+    public BulkActionResult deprovision(final String etag, final long roleId, final List<StatusBean> statuses) {
+        BulkActionResult result;
+        synchronized (this) {
+            RoleService service = getService(etag, RoleService.class);
+            result = service.bulkDeassociation(roleId, ResourceDeassociationActionType.DEPROVISION,
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class)).
+                    readEntity(BulkActionResult.class);
+            resetClient(RoleService.class);
+        }
+        return result;
+    }
+
+    public BulkActionResult provision(final String etag, final long roleId, final List<StatusBean> statuses) {
+        BulkActionResult result;
+        synchronized (this) {
+            RoleService service = getService(etag, RoleService.class);
+            result = service.bulkAssociation(roleId, ResourceAssociationActionType.PROVISION,
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class)).
+                    readEntity(BulkActionResult.class);
+            resetClient(RoleService.class);
+        }
+        return result;
+    }
+
+    public BulkActionResult unassign(final String etag, final long roleId, final List<StatusBean> statuses) {
+        BulkActionResult result;
+        synchronized (this) {
+            RoleService service = getService(etag, RoleService.class);
+            result = service.bulkDeassociation(roleId, ResourceDeassociationActionType.UNASSIGN,
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class)).
+                    readEntity(BulkActionResult.class);
+            resetClient(RoleService.class);
+        }
+        return result;
+    }
+
+    public BulkActionResult assign(final String etag, final long roleId, final List<StatusBean> statuses) {
+        BulkActionResult result;
+        synchronized (this) {
+            RoleService service = getService(etag, RoleService.class);
+            result = service.bulkAssociation(roleId, ResourceAssociationActionType.ASSIGN,
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class)).
+                    readEntity(BulkActionResult.class);
+            resetClient(RoleService.class);
+        }
+        return result;
     }
 }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserRestClient.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserRestClient.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserRestClient.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserRestClient.java Thu Jun 26 09:56:06 2014
@@ -25,13 +25,13 @@ import org.apache.syncope.common.mod.Use
 import org.apache.syncope.common.services.ResourceService;
 import org.apache.syncope.common.services.UserService;
 import org.apache.syncope.common.reqres.BulkAction;
-import org.apache.syncope.common.reqres.BulkActionResult;
 import org.apache.syncope.common.to.ConnObjectTO;
 import org.apache.syncope.common.wrap.ResourceName;
 import org.apache.syncope.common.to.UserTO;
 import org.apache.syncope.common.util.CollectionWrapper;
 import org.apache.syncope.common.SyncopeClientException;
 import org.apache.syncope.common.mod.ResourceAssociationMod;
+import org.apache.syncope.common.reqres.BulkActionResult;
 import org.apache.syncope.common.types.ResourceAssociationActionType;
 import org.apache.syncope.common.types.ResourceDeassociationActionType;
 import org.apache.syncope.common.types.SubjectType;
@@ -44,7 +44,7 @@ import org.springframework.stereotype.Co
  * Console client for invoking rest users services.
  */
 @Component
-public class UserRestClient extends AbstractAttributableRestClient {
+public class UserRestClient extends AbstractSubjectRestClient {
 
     private static final long serialVersionUID = -1575748964398293968L;
 
@@ -63,13 +63,25 @@ public class UserRestClient extends Abst
         return response.readEntity(UserTO.class);
     }
 
-    public UserTO update(final UserMod userMod) {
-        return getService(UserService.class).update(userMod.getId(), userMod).readEntity(UserTO.class);
+    public UserTO update(final String etag, final UserMod userMod) {
+        UserTO result;
+        synchronized (this) {
+            UserService service = getService(etag, UserService.class);
+            result = service.update(userMod.getId(), userMod).readEntity(UserTO.class);
+            resetClient(UserService.class);
+        }
+        return result;
     }
 
     @Override
-    public UserTO delete(final Long id) {
-        return getService(UserService.class).delete(id).readEntity(UserTO.class);
+    public UserTO delete(final String etag, final Long id) {
+        UserTO result;
+        synchronized (this) {
+            UserService service = getService(etag, UserService.class);
+            result = service.delete(id).readEntity(UserTO.class);
+            resetClient(UserService.class);
+        }
+        return result;
     }
 
     public UserTO read(final Long id) {
@@ -97,73 +109,120 @@ public class UserRestClient extends Abst
         return getService(ResourceService.class).getConnectorObject(resourceName, SubjectType.USER, id);
     }
 
-    public void suspend(final long userId, final List<StatusBean> statuses) {
+    public void suspend(final String etag, final long userId, final List<StatusBean> statuses) {
         StatusMod statusMod = StatusUtils.buildStatusMod(statuses, false);
         statusMod.setType(StatusMod.ModType.SUSPEND);
-        getService(UserService.class).status(userId, statusMod);
+        synchronized (this) {
+            UserService service = getService(etag, UserService.class);
+            service.status(userId, statusMod);
+            resetClient(UserService.class);
+        }
     }
 
-    public void reactivate(final long userId, final List<StatusBean> statuses) {
+    public void reactivate(final String etag, final long userId, final List<StatusBean> statuses) {
         StatusMod statusMod = StatusUtils.buildStatusMod(statuses, true);
         statusMod.setType(StatusMod.ModType.REACTIVATE);
-        getService(UserService.class).status(userId, statusMod);
+        synchronized (this) {
+            UserService service = getService(etag, UserService.class);
+            service.status(userId, statusMod);
+            resetClient(UserService.class);
+        }
     }
 
     @Override
-    public BulkActionResult bulkAction(final BulkAction action) {
-        return getService(UserService.class).bulk(action);
+    public void bulkAction(final BulkAction action) {
+        getService(UserService.class).bulk(action);
     }
 
-    public BulkActionResult unlink(final long userId, final List<StatusBean> statuses) {
-        return getService(UserService.class).bulkDeassociation(userId, ResourceDeassociationActionType.UNLINK,
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class))
-                .readEntity(BulkActionResult.class);
+    public void unlink(final String etag, final long userId, final List<StatusBean> statuses) {
+        synchronized (this) {
+            UserService service = getService(etag, UserService.class);
+            service.bulkDeassociation(userId, ResourceDeassociationActionType.UNLINK,
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class));
+            resetClient(UserService.class);
+        }
     }
 
-    public BulkActionResult link(final long userId, final List<StatusBean> statuses) {
-        final ResourceAssociationMod associationMod = new ResourceAssociationMod();
-        associationMod.getTargetResources().addAll(
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class));
+    public void link(final String etag, final long userId, final List<StatusBean> statuses) {
+        synchronized (this) {
+            UserService service = getService(etag, UserService.class);
+
+            final ResourceAssociationMod associationMod = new ResourceAssociationMod();
+            associationMod.getTargetResources().addAll(
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class));
+            service.bulkAssociation(userId, ResourceAssociationActionType.LINK, associationMod);
 
-        return getService(UserService.class).bulkAssociation(userId, ResourceAssociationActionType.LINK, associationMod)
-                .readEntity(BulkActionResult.class);
+            resetClient(UserService.class);
+        }
     }
 
-    public BulkActionResult deprovision(final long userId, final List<StatusBean> statuses) {
-        return getService(UserService.class).bulkDeassociation(userId, ResourceDeassociationActionType.DEPROVISION,
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class))
-                .readEntity(BulkActionResult.class);
+    public BulkActionResult deprovision(final String etag, final long userId, final List<StatusBean> statuses) {
+        BulkActionResult result;
+        synchronized (this) {
+            UserService service = getService(etag, UserService.class);
+            result = service.bulkDeassociation(userId, ResourceDeassociationActionType.DEPROVISION,
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class)).
+                    readEntity(BulkActionResult.class);
+            resetClient(UserService.class);
+        }
+        return result;
     }
 
-    public BulkActionResult provision(
-            final long userId, final List<StatusBean> statuses, final boolean changepwd, final String password) {
-        final ResourceAssociationMod associationMod = new ResourceAssociationMod();
-        associationMod.getTargetResources().addAll(
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class));
-        associationMod.setChangePwd(changepwd);
-        associationMod.setPassword(password);
+    public BulkActionResult provision(final String etag, final long userId,
+            final List<StatusBean> statuses, final boolean changepwd, final String password) {
 
-        return getService(UserService.class)
-                .bulkAssociation(userId, ResourceAssociationActionType.PROVISION, associationMod)
-                .readEntity(BulkActionResult.class);
+        BulkActionResult result;
+        synchronized (this) {
+            UserService service = getService(etag, UserService.class);
+
+            final ResourceAssociationMod associationMod = new ResourceAssociationMod();
+            associationMod.getTargetResources().addAll(
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class));
+            associationMod.setChangePwd(changepwd);
+            associationMod.setPassword(password);
+
+            result = service.bulkAssociation(userId, ResourceAssociationActionType.PROVISION, associationMod).
+                    readEntity(BulkActionResult.class);
+            resetClient(UserService.class);
+        }
+        return result;
     }
 
-    public BulkActionResult unassign(final long userId, final List<StatusBean> statuses) {
-        return getService(UserService.class).bulkDeassociation(userId, ResourceDeassociationActionType.UNASSIGN,
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class))
-                .readEntity(BulkActionResult.class);
+    public BulkActionResult unassign(final String etag, final long userId, final List<StatusBean> statuses) {
+        BulkActionResult result;
+        synchronized (this) {
+            UserService service = getService(etag, UserService.class);
+            result = service.bulkDeassociation(userId, ResourceDeassociationActionType.UNASSIGN,
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class)).
+                    readEntity(BulkActionResult.class);
+            resetClient(UserService.class);
+        }
+        return result;
     }
 
-    public BulkActionResult assign(
-            final long userId, final List<StatusBean> statuses, final boolean changepwd, final String password) {
-        final ResourceAssociationMod associationMod = new ResourceAssociationMod();
-        associationMod.getTargetResources().addAll(
-                CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(), ResourceName.class));
-        associationMod.setChangePwd(changepwd);
-        associationMod.setPassword(password);
+    public BulkActionResult assign(final String etag, final long userId,
+            final List<StatusBean> statuses, final boolean changepwd, final String password) {
 
-        return getService(UserService.class).bulkAssociation(userId, ResourceAssociationActionType.ASSIGN,
-                associationMod)
-                .readEntity(BulkActionResult.class);
+        BulkActionResult result;
+        synchronized (this) {
+            UserService service = getService(etag, UserService.class);
+
+            final ResourceAssociationMod associationMod = new ResourceAssociationMod();
+            associationMod.getTargetResources().addAll(
+                    CollectionWrapper.wrap(StatusUtils.buildStatusMod(statuses).getResourceNames(),
+                            ResourceName.class));
+            associationMod.setChangePwd(changepwd);
+            associationMod.setPassword(password);
+
+            result = service.bulkAssociation(userId, ResourceAssociationActionType.ASSIGN, associationMod).
+                    readEntity(BulkActionResult.class);
+            resetClient(UserService.class);
+        }
+        return result;
     }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/utils/RestServiceExceptionMapper.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/utils/RestServiceExceptionMapper.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/utils/RestServiceExceptionMapper.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/utils/RestServiceExceptionMapper.java Thu Jun 26 09:56:06 2014
@@ -103,6 +103,7 @@ public class RestServiceExceptionMapper 
                 // process JAX-RS validation errors
                 if (builder == null && ex instanceof ValidationException) {
                     builder = JAXRSUtils.fromResponse(validationEM.toResponse((ValidationException) ex)).
+                            header(RESTHeaders.ERROR_CODE, ClientExceptionType.RESTValidation.getHeaderValue()).
                             header(RESTHeaders.ERROR_INFO,
                                     ClientExceptionType.RESTValidation.getInfoHeaderValue(getExMessage(ex)));
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/services/AbstractServiceImpl.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/services/AbstractServiceImpl.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/services/AbstractServiceImpl.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/services/AbstractServiceImpl.java Thu Jun 26 09:56:06 2014
@@ -24,6 +24,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.EntityTag;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
@@ -81,7 +82,7 @@ abstract class AbstractServiceImpl imple
      * @param entity the entity just created
      * @return response to successful <tt>create</tt> request
      */
-    protected Response.ResponseBuilder createResponse(final Object id, final Object entity) {
+    protected Response createResponse(final Object id, final Object entity) {
         URI location = uriInfo.getAbsolutePathBuilder().path(String.valueOf(id)).build();
 
         Response.ResponseBuilder builder = Response.
@@ -103,7 +104,7 @@ abstract class AbstractServiceImpl imple
             builder = builder.header(RESTHeaders.PREFERENCE_APPLIED, getPreference().toString());
         }
 
-        return builder;
+        return builder.build();
     }
 
     /**
@@ -112,7 +113,7 @@ abstract class AbstractServiceImpl imple
      * @param entity the entity just modified
      * @return response to successful modification request
      */
-    protected Response.ResponseBuilder modificationResponse(final Object entity) {
+    protected Response modificationResponse(final Object entity) {
         Response.ResponseBuilder builder;
         switch (getPreference()) {
             case RETURN_NO_CONTENT:
@@ -129,7 +130,16 @@ abstract class AbstractServiceImpl imple
             builder = builder.header(RESTHeaders.PREFERENCE_APPLIED, getPreference().toString());
         }
 
-        return builder;
+        return builder.build();
+    }
+
+    protected void checkETag(final String etag) {
+        Response.ResponseBuilder builder = messageContext.getRequest().evaluatePreconditions(new EntityTag(etag));
+        if (builder != null) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.ConcurrentModification);
+            sce.getElements().add("Mismatching ETag value");
+            throw sce;
+        }
     }
 
     protected SearchCond getSearchCond(final String fiql) {
@@ -180,7 +190,7 @@ abstract class AbstractServiceImpl imple
      * @param page current page
      * @param size requested size
      * @param totalCount total result size (not considering pagination)
-     * @return
+     * @return paged result
      */
     protected <T extends AbstractBaseBean> PagedResult<T> buildPagedResult(
             final List<T> list, final int page, final int size, final int totalCount) {

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/services/RoleServiceImpl.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/services/RoleServiceImpl.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/services/RoleServiceImpl.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/services/RoleServiceImpl.java Thu Jun 26 09:56:06 2014
@@ -20,10 +20,7 @@ package org.apache.syncope.core.services
 
 import java.util.List;
 
-import javax.ws.rs.core.EntityTag;
 import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.ResponseBuilder;
-
 import org.apache.syncope.common.mod.RoleMod;
 import org.apache.syncope.common.reqres.BulkActionResult;
 import org.apache.syncope.common.services.RoleService;
@@ -54,20 +51,17 @@ public class RoleServiceImpl extends Abs
     @Override
     public Response create(final RoleTO roleTO) {
         RoleTO created = controller.create(roleTO);
-        return createResponse(created.getId(), created).build();
+        return createResponse(created.getId(), created);
     }
 
     @Override
     public Response delete(final Long roleId) {
         RoleTO role = controller.read(roleId);
 
-        ResponseBuilder builder = messageContext.getRequest().evaluatePreconditions(new EntityTag(role.getETagValue()));
-        if (builder == null) {
-            RoleTO deleted = controller.delete(roleId);
-            builder = modificationResponse(deleted);
-        }
+        checkETag(role.getETagValue());
 
-        return builder.build();
+        RoleTO deleted = controller.delete(roleId);
+        return modificationResponse(deleted);
     }
 
     @Override
@@ -133,14 +127,11 @@ public class RoleServiceImpl extends Abs
     public Response update(final Long roleId, final RoleMod roleMod) {
         RoleTO role = controller.read(roleId);
 
-        ResponseBuilder builder = messageContext.getRequest().evaluatePreconditions(new EntityTag(role.getETagValue()));
-        if (builder == null) {
-            roleMod.setId(roleId);
-            RoleTO updated = controller.update(roleMod);
-            builder = modificationResponse(updated);
-        }
+        checkETag(role.getETagValue());
 
-        return builder.build();
+        roleMod.setId(roleId);
+        RoleTO updated = controller.update(roleMod);
+        return modificationResponse(updated);
     }
 
     @Override
@@ -149,45 +140,41 @@ public class RoleServiceImpl extends Abs
 
         RoleTO role = controller.read(roleId);
 
-        ResponseBuilder builder = messageContext.getRequest().evaluatePreconditions(new EntityTag(role.getETagValue()));
-        if (builder == null) {
-            RoleTO updated;
-
-            switch (type) {
-                case UNLINK:
-                    updated = controller.unlink(roleId, CollectionWrapper.unwrap(resourceNames));
-                    break;
-
-                case UNASSIGN:
-                    updated = controller.unassign(roleId, CollectionWrapper.unwrap(resourceNames));
-                    break;
-
-                case DEPROVISION:
-                    updated = controller.deprovision(roleId, CollectionWrapper.unwrap(resourceNames));
-                    break;
+        checkETag(role.getETagValue());
 
-                default:
-                    updated = controller.read(roleId);
-            }
+        RoleTO updated;
+        switch (type) {
+            case UNLINK:
+                updated = controller.unlink(roleId, CollectionWrapper.unwrap(resourceNames));
+                break;
+
+            case UNASSIGN:
+                updated = controller.unassign(roleId, CollectionWrapper.unwrap(resourceNames));
+                break;
+
+            case DEPROVISION:
+                updated = controller.deprovision(roleId, CollectionWrapper.unwrap(resourceNames));
+                break;
 
-            final BulkActionResult res = new BulkActionResult();
+            default:
+                updated = controller.read(roleId);
+        }
 
-            if (type == ResourceDeassociationActionType.UNLINK) {
-                for (ResourceName resourceName : resourceNames) {
-                    res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
-                            ? BulkActionResult.Status.FAILURE
-                            : BulkActionResult.Status.SUCCESS);
-                }
-            } else {
-                for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
-                    res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
-                }
-            }
+        final BulkActionResult res = new BulkActionResult();
 
-            builder = modificationResponse(res);
+        if (type == ResourceDeassociationActionType.UNLINK) {
+            for (ResourceName resourceName : resourceNames) {
+                res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
+                        ? BulkActionResult.Status.FAILURE
+                        : BulkActionResult.Status.SUCCESS);
+            }
+        } else {
+            for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
+                res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
+            }
         }
 
-        return builder.build();
+        return modificationResponse(res);
     }
 
     @Override
@@ -196,44 +183,40 @@ public class RoleServiceImpl extends Abs
 
         RoleTO role = controller.read(roleId);
 
-        ResponseBuilder builder = messageContext.getRequest().evaluatePreconditions(new EntityTag(role.getETagValue()));
-        if (builder == null) {
-            RoleTO updated;
-
-            switch (type) {
-                case LINK:
-                    updated = controller.link(roleId, CollectionWrapper.unwrap(resourceNames));
-                    break;
-
-                case ASSIGN:
-                    updated = controller.assign(roleId, CollectionWrapper.unwrap(resourceNames), false, null);
-                    break;
-
-                case PROVISION:
-                    updated = controller.provision(roleId, CollectionWrapper.unwrap(resourceNames), false, null);
-                    break;
+        checkETag(role.getETagValue());
 
-                default:
-                    updated = controller.read(roleId);
-            }
+        RoleTO updated;
+        switch (type) {
+            case LINK:
+                updated = controller.link(roleId, CollectionWrapper.unwrap(resourceNames));
+                break;
+
+            case ASSIGN:
+                updated = controller.assign(roleId, CollectionWrapper.unwrap(resourceNames), false, null);
+                break;
+
+            case PROVISION:
+                updated = controller.provision(roleId, CollectionWrapper.unwrap(resourceNames), false, null);
+                break;
+
+            default:
+                updated = controller.read(roleId);
+        }
 
-            final BulkActionResult res = new BulkActionResult();
+        final BulkActionResult res = new BulkActionResult();
 
-            if (type == ResourceAssociationActionType.LINK) {
-                for (ResourceName resourceName : resourceNames) {
-                    res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
-                            ? BulkActionResult.Status.FAILURE
-                            : BulkActionResult.Status.SUCCESS);
-                }
-            } else {
-                for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
-                    res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
-                }
+        if (type == ResourceAssociationActionType.LINK) {
+            for (ResourceName resourceName : resourceNames) {
+                res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
+                        ? BulkActionResult.Status.FAILURE
+                        : BulkActionResult.Status.SUCCESS);
+            }
+        } else {
+            for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
+                res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
             }
-
-            builder = modificationResponse(res);
         }
 
-        return builder.build();
+        return modificationResponse(res);
     }
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserSelfServiceImpl.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserSelfServiceImpl.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserSelfServiceImpl.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserSelfServiceImpl.java Thu Jun 26 09:56:06 2014
@@ -52,7 +52,7 @@ public class UserSelfServiceImpl extends
         }
 
         UserTO created = controller.createSelf(userTO);
-        return createResponse(created.getId(), created).build();
+        return createResponse(created.getId(), created);
     }
 
     @Override
@@ -64,13 +64,13 @@ public class UserSelfServiceImpl extends
     public Response update(final Long userId, final UserMod userMod) {
         userMod.setId(userId);
         UserTO updated = controller.updateSelf(userMod);
-        return modificationResponse(updated).build();
+        return modificationResponse(updated);
     }
 
     @Override
     public Response delete() {
         UserTO deleted = controller.deleteSelf();
-        return modificationResponse(deleted).build();
+        return modificationResponse(deleted);
     }
 
 }

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserServiceImpl.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserServiceImpl.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserServiceImpl.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserServiceImpl.java Thu Jun 26 09:56:06 2014
@@ -19,10 +19,8 @@
 package org.apache.syncope.core.services;
 
 import java.util.List;
-import javax.ws.rs.core.EntityTag;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.ResponseBuilder;
 import org.apache.syncope.common.mod.ResourceAssociationMod;
 import org.apache.syncope.common.mod.StatusMod;
 import org.apache.syncope.common.mod.UserMod;
@@ -66,20 +64,17 @@ public class UserServiceImpl extends Abs
     @Override
     public Response create(final UserTO userTO) {
         UserTO created = controller.create(userTO);
-        return createResponse(created.getId(), created).build();
+        return createResponse(created.getId(), created);
     }
 
     @Override
     public Response delete(final Long userId) {
         UserTO user = controller.read(userId);
 
-        ResponseBuilder builder = messageContext.getRequest().evaluatePreconditions(new EntityTag(user.getETagValue()));
-        if (builder == null) {
-            UserTO deleted = controller.delete(userId);
-            builder = modificationResponse(deleted);
-        }
+        checkETag(user.getETagValue());
 
-        return builder.build();
+        UserTO deleted = controller.delete(userId);
+        return modificationResponse(deleted);
     }
 
     @Override
@@ -135,28 +130,22 @@ public class UserServiceImpl extends Abs
     public Response update(final Long userId, final UserMod userMod) {
         UserTO user = controller.read(userId);
 
-        ResponseBuilder builder = messageContext.getRequest().evaluatePreconditions(new EntityTag(user.getETagValue()));
-        if (builder == null) {
-            userMod.setId(userId);
-            UserTO updated = controller.update(userMod);
-            builder = modificationResponse(updated);
-        }
+        checkETag(user.getETagValue());
 
-        return builder.build();
+        userMod.setId(userId);
+        UserTO updated = controller.update(userMod);
+        return modificationResponse(updated);
     }
 
     @Override
     public Response status(final Long userId, final StatusMod statusMod) {
         UserTO user = controller.read(userId);
 
-        ResponseBuilder builder = messageContext.getRequest().evaluatePreconditions(new EntityTag(user.getETagValue()));
-        if (builder == null) {
-            statusMod.setId(userId);
-            UserTO updated = controller.status(statusMod);
-            builder = modificationResponse(updated);
-        }
+        checkETag(user.getETagValue());
 
-        return builder.build();
+        statusMod.setId(userId);
+        UserTO updated = controller.status(statusMod);
+        return modificationResponse(updated);
     }
 
     @Override
@@ -165,46 +154,41 @@ public class UserServiceImpl extends Abs
 
         final UserTO user = controller.read(userId);
 
-        ResponseBuilder builder = messageContext.getRequest().evaluatePreconditions(new EntityTag(user.getETagValue()));
-
-        if (builder == null) {
-            UserTO updated;
+        checkETag(user.getETagValue());
 
-            switch (type) {
-                case UNLINK:
-                    updated = controller.unlink(userId, CollectionWrapper.unwrap(resourceNames));
-                    break;
-
-                case UNASSIGN:
-                    updated = controller.unassign(userId, CollectionWrapper.unwrap(resourceNames));
-                    break;
-
-                case DEPROVISION:
-                    updated = controller.deprovision(userId, CollectionWrapper.unwrap(resourceNames));
-                    break;
+        UserTO updated;
+        switch (type) {
+            case UNLINK:
+                updated = controller.unlink(userId, CollectionWrapper.unwrap(resourceNames));
+                break;
+
+            case UNASSIGN:
+                updated = controller.unassign(userId, CollectionWrapper.unwrap(resourceNames));
+                break;
+
+            case DEPROVISION:
+                updated = controller.deprovision(userId, CollectionWrapper.unwrap(resourceNames));
+                break;
 
-                default:
-                    updated = controller.read(userId);
-            }
+            default:
+                updated = controller.read(userId);
+        }
 
-            final BulkActionResult res = new BulkActionResult();
+        final BulkActionResult res = new BulkActionResult();
 
-            if (type == ResourceDeassociationActionType.UNLINK) {
-                for (ResourceName resourceName : resourceNames) {
-                    res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
-                            ? BulkActionResult.Status.FAILURE
-                            : BulkActionResult.Status.SUCCESS);
-                }
-            } else {
-                for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
-                    res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
-                }
+        if (type == ResourceDeassociationActionType.UNLINK) {
+            for (ResourceName resourceName : resourceNames) {
+                res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
+                        ? BulkActionResult.Status.FAILURE
+                        : BulkActionResult.Status.SUCCESS);
+            }
+        } else {
+            for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
+                res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
             }
-
-            builder = modificationResponse(res);
         }
 
-        return builder.build();
+        return modificationResponse(res);
     }
 
     @Override
@@ -213,55 +197,51 @@ public class UserServiceImpl extends Abs
 
         final UserTO user = controller.read(userId);
 
-        ResponseBuilder builder = messageContext.getRequest().evaluatePreconditions(new EntityTag(user.getETagValue()));
-        if (builder == null) {
-            UserTO updated;
-
-            switch (type) {
-                case LINK:
-                    updated = controller.link(
-                            userId,
-                            CollectionWrapper.unwrap(associationMod.getTargetResources()));
-                    break;
-
-                case ASSIGN:
-                    updated = controller.assign(
-                            userId,
-                            CollectionWrapper.unwrap(associationMod.getTargetResources()),
-                            associationMod.isChangePwd(),
-                            associationMod.getPassword());
-                    break;
-
-                case PROVISION:
-                    updated = controller.provision(
-                            userId,
-                            CollectionWrapper.unwrap(associationMod.getTargetResources()),
-                            associationMod.isChangePwd(),
-                            associationMod.getPassword());
-                    break;
+        checkETag(user.getETagValue());
 
-                default:
-                    updated = controller.read(userId);
-            }
+        UserTO updated;
+        switch (type) {
+            case LINK:
+                updated = controller.link(
+                        userId,
+                        CollectionWrapper.unwrap(associationMod.getTargetResources()));
+                break;
+
+            case ASSIGN:
+                updated = controller.assign(
+                        userId,
+                        CollectionWrapper.unwrap(associationMod.getTargetResources()),
+                        associationMod.isChangePwd(),
+                        associationMod.getPassword());
+                break;
+
+            case PROVISION:
+                updated = controller.provision(
+                        userId,
+                        CollectionWrapper.unwrap(associationMod.getTargetResources()),
+                        associationMod.isChangePwd(),
+                        associationMod.getPassword());
+                break;
+
+            default:
+                updated = controller.read(userId);
+        }
 
-            final BulkActionResult res = new BulkActionResult();
+        final BulkActionResult res = new BulkActionResult();
 
-            if (type == ResourceAssociationActionType.LINK) {
-                for (ResourceName resourceName : associationMod.getTargetResources()) {
-                    res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
-                            ? BulkActionResult.Status.FAILURE
-                            : BulkActionResult.Status.SUCCESS);
-                }
-            } else {
-                for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
-                    res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
-                }
+        if (type == ResourceAssociationActionType.LINK) {
+            for (ResourceName resourceName : associationMod.getTargetResources()) {
+                res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
+                        ? BulkActionResult.Status.FAILURE
+                        : BulkActionResult.Status.SUCCESS);
+            }
+        } else {
+            for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
+                res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
             }
-
-            builder = modificationResponse(res);
         }
 
-        return builder.build();
+        return modificationResponse(res);
     }
 
     @Override

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java?rev=1605721&r1=1605720&r2=1605721&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java Thu Jun 26 09:56:06 2014
@@ -37,7 +37,6 @@ import java.util.List;
 import javax.naming.NamingException;
 import javax.ws.rs.core.EntityTag;
 import javax.ws.rs.core.Response;
-import javax.xml.ws.WebServiceException;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.helpers.IOUtils;
@@ -1393,7 +1392,7 @@ public class UserTestITCase extends Abst
         final String originalCAValue = defaultCA.getValues().get(0);
         defaultCA.getValues().set(0, "MD5");
         configurationService.set(defaultCA.getSchema(), defaultCA);
-        
+
         AttributeTO newCA = configurationService.read(defaultCA.getSchema());
         assertEquals(defaultCA, newCA);
 
@@ -1410,7 +1409,7 @@ public class UserTestITCase extends Abst
 
         defaultCA.getValues().set(0, originalCAValue);
         configurationService.set(defaultCA.getSchema(), defaultCA);
-        
+
         AttributeTO oldCA = configurationService.read(defaultCA.getSchema());
         assertEquals(defaultCA, oldCA);
     }
@@ -2183,8 +2182,8 @@ public class UserTestITCase extends Abst
         try {
             ifMatchService.update(userMod.getId(), userMod);
             fail();
-        } catch (WebServiceException e) {
-            assertTrue(e.getMessage().endsWith(Response.Status.PRECONDITION_FAILED.name()));
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.ConcurrentModification, e.getType());
         }
 
         userTO = userService.read(userTO.getId());