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 2013/02/22 17:31:20 UTC

svn commit: r1449107 - in /syncope/trunk: client/src/main/java/org/apache/syncope/client/rest/utils/ common/src/main/java/org/apache/syncope/common/types/ common/src/main/java/org/apache/syncope/common/validation/ console/src/main/java/org/apache/synco...

Author: ilgrosso
Date: Fri Feb 22 16:31:19 2013
New Revision: 1449107

URL: http://svn.apache.org/r1449107
Log:
[SYNCOPE-323] Check added in the REST create methods, throwing exception mapped to HTTP 409 CONFLICT as suggested

Modified:
    syncope/trunk/client/src/main/java/org/apache/syncope/client/rest/utils/RestClientExceptionMapper.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/types/SyncopeClientExceptionType.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/validation/SyncopeClientCompositeErrorException.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/validation/SyncopeClientErrorHandler.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/SchemaModalPage.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/ConnInstanceController.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/DerivedSchemaController.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/ResourceController.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/SchemaController.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/VirtualSchemaController.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/utils/RestServiceExceptionMapper.java
    syncope/trunk/core/src/main/webapp/syncopeClientError.jsp
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/DerivedSchemaTestITCase.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/ResourceTestITCase.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/SchemaTestITCase.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/VirtualSchemaTestITCase.java

Modified: syncope/trunk/client/src/main/java/org/apache/syncope/client/rest/utils/RestClientExceptionMapper.java
URL: http://svn.apache.org/viewvc/syncope/trunk/client/src/main/java/org/apache/syncope/client/rest/utils/RestClientExceptionMapper.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/client/src/main/java/org/apache/syncope/client/rest/utils/RestClientExceptionMapper.java (original)
+++ syncope/trunk/client/src/main/java/org/apache/syncope/client/rest/utils/RestClientExceptionMapper.java Fri Feb 22 16:31:19 2013
@@ -72,8 +72,8 @@ public class RestClientExceptionMapper i
 
         } else {
             // 4. All other codes are mapped to runtime exception with HTTP code information
-            ex = new WebServiceException(String.format("Remote exception with status code: %s", Response.Status
-                    .fromStatusCode(statusCode).name()));
+            ex = new WebServiceException(String.format("Remote exception with status code: %s",
+                    Response.Status.fromStatusCode(statusCode).name()));
         }
         LOG.error("Exception thrown by REST methods: " + ex.getMessage(), ex);
         return ex;

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/types/SyncopeClientExceptionType.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/types/SyncopeClientExceptionType.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/types/SyncopeClientExceptionType.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/types/SyncopeClientExceptionType.java Fri Feb 22 16:31:19 2013
@@ -23,9 +23,10 @@ import javax.xml.bind.annotation.XmlEnum
 @XmlEnum
 public enum SyncopeClientExceptionType {
 
+    AssociatedResources("Syncope.AssociatedResources", "Syncope.AssociatedResources.name"),
     Deadlock("Syncope.Deadlock", ""),
     DataIntegrityViolation("Syncope.DataIntegrityViolation", "Syncope.DataIntegrityViolation.name"),
-    ExistingResource("Syncope.ExistingResource", "Syncope.ExistingResource.name"),
+    EntityExists("Syncope.EntityExists", "Syncope.EntityExists.name"),
     GenericPersistence("Syncope.GenericPersistence", "Syncope.GenericPersistence.cause"),
     InvalidLogger("Syncope.InvalidLogger", "Syncope.InvalidLogger.message"),
     InvalidConnInstance("Syncope.InvalidConnInstance", "Syncope.InvalidConnInstance.message"),

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/validation/SyncopeClientCompositeErrorException.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/validation/SyncopeClientCompositeErrorException.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/validation/SyncopeClientCompositeErrorException.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/validation/SyncopeClientCompositeErrorException.java Fri Feb 22 16:31:19 2013
@@ -27,6 +27,8 @@ import org.springframework.web.client.Ht
 
 public class SyncopeClientCompositeErrorException extends HttpClientErrorException {
 
+    private static final long serialVersionUID = 7882118041134372129L;
+
     private Set<SyncopeClientException> exceptions;
 
     public SyncopeClientCompositeErrorException(HttpStatus statusCode) {
@@ -43,11 +45,9 @@ public class SyncopeClientCompositeError
     }
 
     public SyncopeClientException getException(SyncopeClientExceptionType exceptionType) {
-
         boolean found = false;
         SyncopeClientException syncopeClientException = null;
         for (Iterator<SyncopeClientException> itor = exceptions.iterator(); itor.hasNext() && !found;) {
-
             syncopeClientException = itor.next();
             if (syncopeClientException.getType().equals(exceptionType)) {
                 found = true;

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/validation/SyncopeClientErrorHandler.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/validation/SyncopeClientErrorHandler.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/validation/SyncopeClientErrorHandler.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/validation/SyncopeClientErrorHandler.java Fri Feb 22 16:31:19 2013
@@ -39,7 +39,9 @@ public class SyncopeClientErrorHandler e
      */
     private static final Logger LOG = LoggerFactory.getLogger(SyncopeClientErrorHandler.class);
 
-    private static final HttpStatus[] MANAGED_STATUSES = {HttpStatus.BAD_REQUEST, HttpStatus.NOT_FOUND};
+    private static final HttpStatus[] MANAGED_STATUSES = {
+        HttpStatus.BAD_REQUEST, HttpStatus.NOT_FOUND, HttpStatus.CONFLICT
+    };
 
     @Override
     public void handleError(final ClientHttpResponse response) throws IOException {

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/SchemaModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/SchemaModalPage.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/SchemaModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/SchemaModalPage.java Fri Feb 22 16:31:19 2013
@@ -30,7 +30,6 @@ import org.apache.syncope.common.to.Sche
 import org.apache.syncope.common.types.AttributableType;
 import org.apache.syncope.common.types.AttributeSchemaType;
 import org.apache.syncope.common.validation.SyncopeClientCompositeErrorException;
-import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
 import org.apache.syncope.console.wicket.markup.html.form.AjaxCheckBoxPanel;
 import org.apache.syncope.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.console.wicket.markup.html.form.AjaxTextFieldPanel;
@@ -40,6 +39,7 @@ import org.apache.wicket.ajax.AjaxReques
 import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
 import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 import org.apache.wicket.markup.html.form.DropDownChoice;
@@ -214,12 +214,12 @@ public class SchemaModalPage extends Abs
         final AjaxCheckBoxPanel uniqueConstraint = new AjaxCheckBoxPanel("uniqueConstraint",
                 getString("uniqueConstraint"), new PropertyModel<Boolean>(schema, "uniqueConstraint"));
 
-        final AjaxButton submit = new ClearIndicatingAjaxButton("apply", new ResourceModel("submit"), pageRef) {
+        final AjaxButton submit = new IndicatingAjaxButton("apply", new ResourceModel("submit")) {
 
             private static final long serialVersionUID = -958724007591692537L;
 
             @Override
-            protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
                 final SchemaTO schemaTO = (SchemaTO) form.getDefaultModelObject();
 
                 schemaTO.setEnumerationValues(getEnumValuesAsString(enumerationValues.getView().getModelObject()));
@@ -254,12 +254,12 @@ public class SchemaModalPage extends Abs
             }
         };
 
-        final AjaxButton cancel = new ClearIndicatingAjaxButton("cancel", new ResourceModel("cancel"), pageRef) {
+        final AjaxButton cancel = new IndicatingAjaxButton("cancel", new ResourceModel("cancel")) {
 
             private static final long serialVersionUID = -958724007591692537L;
 
             @Override
-            protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
                 window.close(target);
             }
         };

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/ConnInstanceController.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/ConnInstanceController.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/ConnInstanceController.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/ConnInstanceController.java Fri Feb 22 16:31:19 2013
@@ -142,7 +142,6 @@ public class ConnInstanceController exte
     @PreAuthorize("hasRole('CONNECTOR_DELETE')")
     @RequestMapping(method = RequestMethod.GET, value = "/delete/{connInstanceId}")
     public ConnInstanceTO delete(@PathVariable("connInstanceId") final Long connInstanceId) {
-
         ConnInstance connInstance = connInstanceDAO.find(connInstanceId);
         if (connInstance == null) {
             throw new NotFoundException("Connector '" + connInstanceId + "'");
@@ -152,13 +151,13 @@ public class ConnInstanceController exte
             SyncopeClientCompositeErrorException scce =
                     new SyncopeClientCompositeErrorException(HttpStatus.BAD_REQUEST);
 
-            SyncopeClientException invalidConnInstance = new SyncopeClientException(
-                    SyncopeClientExceptionType.ExistingResource);
+            SyncopeClientException associatedResources =
+                    new SyncopeClientException(SyncopeClientExceptionType.AssociatedResources);
             for (ExternalResource resource : connInstance.getResources()) {
-                invalidConnInstance.addElement(resource.getName());
+                associatedResources.addElement(resource.getName());
             }
 
-            scce.addException(invalidConnInstance);
+            scce.addException(associatedResources);
             throw scce;
         }
 

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/DerivedSchemaController.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/DerivedSchemaController.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/DerivedSchemaController.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/DerivedSchemaController.java Fri Feb 22 16:31:19 2013
@@ -20,12 +20,16 @@ package org.apache.syncope.core.rest.con
 
 import java.util.ArrayList;
 import java.util.List;
+import javax.persistence.EntityExistsException;
 import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang.StringUtils;
 import org.apache.syncope.common.to.DerivedSchemaTO;
 import org.apache.syncope.common.types.AuditElements.Category;
 import org.apache.syncope.common.types.AuditElements.Result;
 import org.apache.syncope.common.types.AuditElements.SchemaSubCategory;
+import org.apache.syncope.common.types.SyncopeClientExceptionType;
 import org.apache.syncope.common.validation.SyncopeClientCompositeErrorException;
+import org.apache.syncope.common.validation.SyncopeClientException;
 import org.apache.syncope.core.audit.AuditManager;
 import org.apache.syncope.core.persistence.beans.AbstractDerSchema;
 import org.apache.syncope.core.persistence.dao.DerSchemaDAO;
@@ -33,6 +37,7 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.core.rest.data.DerivedSchemaDataBinder;
 import org.apache.syncope.core.util.AttributableUtil;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -56,11 +61,26 @@ public class DerivedSchemaController ext
     @PreAuthorize("hasRole('SCHEMA_CREATE')")
     @RequestMapping(method = RequestMethod.POST, value = "/{kind}/create")
     public DerivedSchemaTO create(final HttpServletResponse response,
-            @RequestBody final DerivedSchemaTO derivedSchemaTO, @PathVariable("kind") final String kind)
-            throws SyncopeClientCompositeErrorException {
+            @RequestBody final DerivedSchemaTO derSchemaTO, @PathVariable("kind") final String kind) {
 
-        AbstractDerSchema derivedSchema = derSchemaDAO.save(
-                binder.create(derivedSchemaTO, getAttributableUtil(kind).newDerSchema()));
+
+        if (StringUtils.isBlank(derSchemaTO.getName())) {
+            SyncopeClientCompositeErrorException sccee =
+                    new SyncopeClientCompositeErrorException(HttpStatus.BAD_REQUEST);
+            SyncopeClientException sce = new SyncopeClientException(SyncopeClientExceptionType.RequiredValuesMissing);
+            sce.addElement("Derived schema name");
+            sccee.addException(sce);
+            throw sccee;
+        }
+
+        AttributableUtil attrUtil = getAttributableUtil(kind);
+
+        if (derSchemaDAO.find(derSchemaTO.getName(), attrUtil.derSchemaClass()) != null) {
+            throw new EntityExistsException(attrUtil.schemaClass().getSimpleName()
+                    + " '" + derSchemaTO.getName() + "'");
+        }
+
+        AbstractDerSchema derivedSchema = derSchemaDAO.save(binder.create(derSchemaTO, attrUtil.newDerSchema()));
 
         auditManager.audit(Category.schema, SchemaSubCategory.createDerived, Result.success,
                 "Successfully created derived schema: " + kind + "/" + derivedSchema.getName());
@@ -72,7 +92,7 @@ public class DerivedSchemaController ext
     @PreAuthorize("hasRole('SCHEMA_DELETE')")
     @RequestMapping(method = RequestMethod.GET, value = "/{kind}/delete/{schema}")
     public DerivedSchemaTO delete(@PathVariable("kind") final String kind,
-            @PathVariable("schema") final String derivedSchemaName) throws NotFoundException {
+            @PathVariable("schema") final String derivedSchemaName) {
 
         Class<? extends AbstractDerSchema> reference = getAttributableUtil(kind).derSchemaClass();
         AbstractDerSchema derivedSchema = derSchemaDAO.find(derivedSchemaName, reference);
@@ -109,7 +129,7 @@ public class DerivedSchemaController ext
     @PreAuthorize("hasRole('SCHEMA_READ')")
     @RequestMapping(method = RequestMethod.GET, value = "/{kind}/read/{derivedSchema}")
     public DerivedSchemaTO read(@PathVariable("kind") final String kind,
-            @PathVariable("derivedSchema") final String derivedSchemaName) throws NotFoundException {
+            @PathVariable("derivedSchema") final String derivedSchemaName) {
 
         Class<? extends AbstractDerSchema> reference = getAttributableUtil(kind).derSchemaClass();
         AbstractDerSchema derivedSchema = derSchemaDAO.find(derivedSchemaName, reference);
@@ -126,7 +146,7 @@ public class DerivedSchemaController ext
     @PreAuthorize("hasRole('SCHEMA_UPDATE')")
     @RequestMapping(method = RequestMethod.POST, value = "/{kind}/update")
     public DerivedSchemaTO update(@RequestBody final DerivedSchemaTO derivedSchemaTO,
-            @PathVariable("kind") final String kind) throws NotFoundException {
+            @PathVariable("kind") final String kind) {
 
         Class<? extends AbstractDerSchema> reference = getAttributableUtil(kind).derSchemaClass();
         AbstractDerSchema derivedSchema = derSchemaDAO.find(derivedSchemaTO.getName(), reference);

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/ResourceController.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/ResourceController.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/ResourceController.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/ResourceController.java Fri Feb 22 16:31:19 2013
@@ -20,7 +20,9 @@ package org.apache.syncope.core.rest.con
 
 import java.util.List;
 import java.util.Set;
+import javax.persistence.EntityExistsException;
 import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang.StringUtils;
 import org.apache.syncope.common.to.ConnObjectTO;
 import org.apache.syncope.common.to.ResourceTO;
 import org.apache.syncope.common.types.AttributableType;
@@ -29,6 +31,9 @@ import org.apache.syncope.common.types.A
 import org.apache.syncope.common.types.AuditElements.ResourceSubCategory;
 import org.apache.syncope.common.types.AuditElements.Result;
 import org.apache.syncope.common.types.MappingPurpose;
+import org.apache.syncope.common.types.SyncopeClientExceptionType;
+import org.apache.syncope.common.validation.SyncopeClientCompositeErrorException;
+import org.apache.syncope.common.validation.SyncopeClientException;
 import org.apache.syncope.core.audit.AuditManager;
 import org.apache.syncope.core.connid.ConnObjectUtil;
 import org.apache.syncope.core.init.ImplementationClassNamesLoader;
@@ -48,6 +53,7 @@ import org.identityconnectors.framework.
 import org.identityconnectors.framework.common.objects.ObjectClass;
 import org.identityconnectors.framework.common.objects.Uid;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
 import org.springframework.transaction.annotation.Transactional;
@@ -84,13 +90,26 @@ public class ResourceController extends 
     private ConnObjectUtil connObjectUtil;
 
     @Autowired
-    private ConnectorFactory connLoader;
+    private ConnectorFactory connFactory;
 
     @PreAuthorize("hasRole('RESOURCE_CREATE')")
     @RequestMapping(method = RequestMethod.POST, value = "/create")
     public ResourceTO create(final HttpServletResponse response, @RequestBody final ResourceTO resourceTO) {
         LOG.debug("Resource creation: {}", resourceTO);
 
+        if (StringUtils.isBlank(resourceTO.getName())) {
+            SyncopeClientCompositeErrorException sccee =
+                    new SyncopeClientCompositeErrorException(HttpStatus.BAD_REQUEST);
+            SyncopeClientException sce = new SyncopeClientException(SyncopeClientExceptionType.RequiredValuesMissing);
+            sce.addElement("Resource name");
+            sccee.addException(sce);
+            throw sccee;
+        }
+
+        if (resourceDAO.find(resourceTO.getName()) != null) {
+            throw new EntityExistsException("Resource '" + resourceTO.getName() + "'");
+        }
+
         ExternalResource resource = resourceDAO.save(binder.create(resourceTO));
 
         auditManager.audit(Category.resource, ResourceSubCategory.create, Result.success,
@@ -203,7 +222,7 @@ public class ResourceController extends 
         AttributableUtil attrUtil = AttributableUtil.getInstance(type);
         ObjectClass objectClass = AttributableType.USER == type ? ObjectClass.ACCOUNT : ObjectClass.GROUP;
 
-        final Connector connector = connLoader.getConnector(resource);
+        final Connector connector = connFactory.getConnector(resource);
 
         final ConnectorObject connectorObject = connector.getObject(objectClass, new Uid(objectId),
                 connector.getOperationOptions(attrUtil.getMappingItems(resource, MappingPurpose.BOTH)));
@@ -231,7 +250,7 @@ public class ResourceController extends 
     public ModelAndView check(@RequestBody final ResourceTO resourceTO) {
         final ConnInstance connInstance = binder.getConnInstance(resourceTO);
 
-        final Connector connector = connLoader.createConnector(connInstance, connInstance.getConfiguration());
+        final Connector connector = connFactory.createConnector(connInstance, connInstance.getConfiguration());
 
         boolean result;
         try {

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/SchemaController.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/SchemaController.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/SchemaController.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/SchemaController.java Fri Feb 22 16:31:19 2013
@@ -20,11 +20,16 @@ package org.apache.syncope.core.rest.con
 
 import java.util.ArrayList;
 import java.util.List;
+import javax.persistence.EntityExistsException;
 import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang.StringUtils;
 import org.apache.syncope.common.to.SchemaTO;
 import org.apache.syncope.common.types.AuditElements.Category;
 import org.apache.syncope.common.types.AuditElements.Result;
 import org.apache.syncope.common.types.AuditElements.SchemaSubCategory;
+import org.apache.syncope.common.types.SyncopeClientExceptionType;
+import org.apache.syncope.common.validation.SyncopeClientCompositeErrorException;
+import org.apache.syncope.common.validation.SyncopeClientException;
 import org.apache.syncope.core.audit.AuditManager;
 import org.apache.syncope.core.persistence.beans.AbstractSchema;
 import org.apache.syncope.core.persistence.dao.NotFoundException;
@@ -32,6 +37,7 @@ import org.apache.syncope.core.persisten
 import org.apache.syncope.core.rest.data.SchemaDataBinder;
 import org.apache.syncope.core.util.AttributableUtil;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -57,7 +63,23 @@ public class SchemaController extends Ab
     public SchemaTO create(final HttpServletResponse response, @RequestBody final SchemaTO schemaTO,
             @PathVariable("kind") final String kind) {
 
-        AbstractSchema schema = getAttributableUtil(kind).newSchema();
+        if (StringUtils.isBlank(schemaTO.getName())) {
+            SyncopeClientCompositeErrorException sccee =
+                    new SyncopeClientCompositeErrorException(HttpStatus.BAD_REQUEST);
+            SyncopeClientException sce = new SyncopeClientException(SyncopeClientExceptionType.RequiredValuesMissing);
+            sce.addElement("Schema name");
+            sccee.addException(sce);
+            throw sccee;
+        }
+
+        AttributableUtil attrUtil = getAttributableUtil(kind);
+
+        if (schemaDAO.find(schemaTO.getName(), attrUtil.schemaClass()) != null) {
+            throw new EntityExistsException(attrUtil.schemaClass().getSimpleName()
+                    + " '" + schemaTO.getName() + "'");
+        }
+
+        AbstractSchema schema = attrUtil.newSchema();
         binder.create(schemaTO, schema);
         schema = schemaDAO.save(schema);
 
@@ -65,7 +87,7 @@ public class SchemaController extends Ab
                 "Successfully created schema: " + kind + "/" + schema.getName());
 
         response.setStatus(HttpServletResponse.SC_CREATED);
-        return binder.getSchemaTO(schema, getAttributableUtil(kind));
+        return binder.getSchemaTO(schema, attrUtil);
     }
 
     @PreAuthorize("hasRole('SCHEMA_DELETE')")

Modified: syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/VirtualSchemaController.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/VirtualSchemaController.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/VirtualSchemaController.java (original)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/VirtualSchemaController.java Fri Feb 22 16:31:19 2013
@@ -20,17 +20,24 @@ package org.apache.syncope.core.rest.con
 
 import java.util.ArrayList;
 import java.util.List;
+import javax.persistence.EntityExistsException;
 import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang.StringUtils;
 import org.apache.syncope.common.to.VirtualSchemaTO;
 import org.apache.syncope.common.types.AuditElements.Category;
 import org.apache.syncope.common.types.AuditElements.Result;
 import org.apache.syncope.common.types.AuditElements.SchemaSubCategory;
+import org.apache.syncope.common.types.SyncopeClientExceptionType;
+import org.apache.syncope.common.validation.SyncopeClientCompositeErrorException;
+import org.apache.syncope.common.validation.SyncopeClientException;
 import org.apache.syncope.core.audit.AuditManager;
 import org.apache.syncope.core.persistence.beans.AbstractVirSchema;
 import org.apache.syncope.core.persistence.dao.NotFoundException;
 import org.apache.syncope.core.persistence.dao.VirSchemaDAO;
 import org.apache.syncope.core.rest.data.VirtualSchemaDataBinder;
+import org.apache.syncope.core.util.AttributableUtil;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -54,10 +61,25 @@ public class VirtualSchemaController ext
     @PreAuthorize("hasRole('SCHEMA_CREATE')")
     @RequestMapping(method = RequestMethod.POST, value = "/{kind}/create")
     public VirtualSchemaTO create(final HttpServletResponse response,
-            @RequestBody final VirtualSchemaTO virtualSchemaTO, @PathVariable("kind") final String kind) {
+            @RequestBody final VirtualSchemaTO virSchemaTO, @PathVariable("kind") final String kind) {
 
-        AbstractVirSchema virSchema = virSchemaDAO.save(binder.create(
-                virtualSchemaTO, getAttributableUtil(kind).newVirSchema()));
+        if (StringUtils.isBlank(virSchemaTO.getName())) {
+            SyncopeClientCompositeErrorException sccee =
+                    new SyncopeClientCompositeErrorException(HttpStatus.BAD_REQUEST);
+            SyncopeClientException sce = new SyncopeClientException(SyncopeClientExceptionType.RequiredValuesMissing);
+            sce.addElement("Virtual schema name");
+            sccee.addException(sce);
+            throw sccee;
+        }
+
+        AttributableUtil attrUtil = getAttributableUtil(kind);
+
+        if (virSchemaDAO.find(virSchemaTO.getName(), attrUtil.virSchemaClass()) != null) {
+            throw new EntityExistsException(attrUtil.schemaClass().getSimpleName()
+                    + " '" + virSchemaTO.getName() + "'");
+        }
+
+        AbstractVirSchema virSchema = virSchemaDAO.save(binder.create(virSchemaTO, attrUtil.newVirSchema()));
 
         auditManager.audit(Category.schema, SchemaSubCategory.createVirtual, Result.success,
                 "Successfully created virtual schema: " + kind + "/" + virSchema.getName());

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=1449107&r1=1449106&r2=1449107&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 Fri Feb 22 16:31:19 2013
@@ -20,6 +20,7 @@ package org.apache.syncope.core.rest.uti
 
 import java.util.Map;
 import java.util.Set;
+import javax.persistence.EntityExistsException;
 import javax.persistence.PersistenceException;
 import javax.ws.rs.BadRequestException;
 import javax.ws.rs.core.HttpHeaders;
@@ -76,6 +77,12 @@ public class RestServiceExceptionMapper 
                     getExMessage(ex));
         }
 
+        if (ex instanceof EntityExistsException) {
+            return buildResponse(Response.status(Response.Status.CONFLICT),
+                    SyncopeClientExceptionType.EntityExists,
+                    getExMessage(ex));
+        }
+
         if (ex instanceof DataIntegrityViolationException) {
             return buildResponse(Response.status(Response.Status.CONFLICT),
                     SyncopeClientExceptionType.DataIntegrityViolation,
@@ -168,8 +175,8 @@ public class RestServiceExceptionMapper 
 
             responseBuilder.header(SyncopeClientErrorHandler.EXCEPTION_TYPE_HEADER, exType.getHeaderValue());
 
-            for (@SuppressWarnings("rawtypes") Map.Entry<Class, Set<EntityViolationType>> violation :
-                    ((InvalidEntityException) ex).getViolations().entrySet()) {
+            for (@SuppressWarnings("rawtypes") Map.Entry<Class, Set<EntityViolationType>> violation
+                    : ((InvalidEntityException) ex).getViolations().entrySet()) {
 
                 for (EntityViolationType violationType : violation.getValue()) {
                     responseBuilder.header(exType.getElementHeaderName(),

Modified: syncope/trunk/core/src/main/webapp/syncopeClientError.jsp
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/webapp/syncopeClientError.jsp?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/core/src/main/webapp/syncopeClientError.jsp (original)
+++ syncope/trunk/core/src/main/webapp/syncopeClientError.jsp Fri Feb 22 16:31:19 2013
@@ -17,13 +17,12 @@ specific language governing permissions 
 under the License.
 --%>
 <%@page isErrorPage="true" session="false" contentType="application/json" pageEncoding="UTF-8"%>
-<%@page import="org.springframework.orm.jpa.JpaSystemException"%>
-<%@page import="org.apache.syncope.common.types.EntityViolationType"%>
 <%@page import="java.util.Set"%>
 <%@page import="java.util.Map"%>
-<%@page import="org.apache.syncope.core.persistence.validation.entity.InvalidEntityException"%>
+<%@page import="javax.persistence.EntityExistsException"%>
 <%@page import="javax.persistence.PersistenceException"%>
-<%@page import="org.springframework.dao.DataIntegrityViolationException"%>
+<%@page import="org.apache.syncope.common.types.EntityViolationType"%>
+<%@page import="org.apache.syncope.core.persistence.validation.entity.InvalidEntityException"%>
 <%@page import="org.apache.syncope.common.services.InvalidSearchConditionException"%>
 <%@page import="org.apache.syncope.core.rest.controller.UnauthorizedRoleException"%>
 <%@page import="org.apache.syncope.core.persistence.dao.MissingConfKeyException"%>
@@ -35,9 +34,11 @@ under the License.
 <%@page import="org.apache.syncope.core.persistence.dao.NotFoundException"%>
 <%@page import="org.identityconnectors.framework.common.exceptions.ConfigurationException"%>
 <%@page import="org.apache.syncope.common.validation.SyncopeClientErrorHandler"%>
+<%@page import="org.apache.syncope.core.rest.controller.AbstractController"%>
 <%@page import="org.slf4j.LoggerFactory"%>
 <%@page import="org.slf4j.Logger"%>
-<%@page import="org.apache.syncope.core.rest.controller.AbstractController"%>
+<%@page import="org.springframework.dao.DataIntegrityViolationException"%>
+<%@page import="org.springframework.orm.jpa.JpaSystemException"%>
 
 <%!    static final Logger LOG = LoggerFactory.getLogger(AbstractController.class);%>
 
@@ -54,8 +55,8 @@ under the License.
 
         response.setHeader(SyncopeClientErrorHandler.EXCEPTION_TYPE_HEADER, exType.getHeaderValue());
 
-        for (Map.Entry<Class, Set<EntityViolationType>> violation :
-                ((InvalidEntityException) ex).getViolations().entrySet()) {
+        for (Map.Entry<Class, Set<EntityViolationType>> violation : ((InvalidEntityException) ex).getViolations().
+                entrySet()) {
 
             for (EntityViolationType violationType : violation.getValue()) {
                 response.addHeader(exType.getElementHeaderName(),
@@ -70,6 +71,12 @@ under the License.
         response.setHeader(SyncopeClientExceptionType.NotFound.getElementHeaderName(), ex.getMessage());
 
         statusCode = HttpServletResponse.SC_NOT_FOUND;
+    } else if (ex instanceof EntityExistsException) {
+        response.setHeader(SyncopeClientErrorHandler.EXCEPTION_TYPE_HEADER,
+                SyncopeClientExceptionType.EntityExists.getHeaderValue());
+        response.setHeader(SyncopeClientExceptionType.EntityExists.getElementHeaderName(), ex.getMessage());
+
+        statusCode = HttpServletResponse.SC_CONFLICT;
     } else if (ex instanceof WorkflowException) {
         response.setHeader(SyncopeClientErrorHandler.EXCEPTION_TYPE_HEADER,
                 SyncopeClientExceptionType.Workflow.getHeaderValue());

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/DerivedSchemaTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/DerivedSchemaTestITCase.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/DerivedSchemaTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/DerivedSchemaTestITCase.java Fri Feb 22 16:31:19 2013
@@ -21,12 +21,13 @@ package org.apache.syncope.core.rest;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.util.List;
 
 import javax.ws.rs.core.Response;
 
-import org.apache.http.HttpStatus;
 import org.apache.syncope.common.to.DerivedSchemaTO;
 import org.apache.syncope.common.types.AttributableType;
 import org.apache.syncope.common.types.SchemaType;
@@ -35,6 +36,7 @@ import org.apache.syncope.common.validat
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
+import org.springframework.http.HttpStatus;
 
 @FixMethodOrder(MethodSorters.JVM)
 public class DerivedSchemaTestITCase extends AbstractTest {
@@ -91,7 +93,7 @@ public class DerivedSchemaTestITCase ext
             // Recreate schema to make test re-runnable
             Response response = createSchema(AttributableType.ROLE, SchemaType.DERIVED, schema);
             assertNotNull(response);
-            assertEquals(HttpStatus.SC_CREATED, response.getStatus());
+            assertEquals(HttpStatus.CREATED.value(), response.getStatus());
         }
         assertNotNull(t);
     }
@@ -118,4 +120,27 @@ public class DerivedSchemaTestITCase ext
                     schema.getName(), schema);
         }
     }
+
+    @Test
+    public void issueSYNCOPE323() {
+        DerivedSchemaTO actual = schemaService.read(AttributableType.ROLE, SchemaType.DERIVED, "rderiveddata");
+        assertNotNull(actual);
+
+        try {
+            createSchema(AttributableType.ROLE, SchemaType.DERIVED, actual);
+            fail();
+        } catch (SyncopeClientCompositeErrorException scce) {
+            assertEquals(HttpStatus.CONFLICT, scce.getStatusCode());
+            assertTrue(scce.hasException(SyncopeClientExceptionType.EntityExists));
+        }
+
+        actual.setName(null);
+        try {
+            createSchema(AttributableType.ROLE, SchemaType.DERIVED, actual);
+            fail();
+        } catch (SyncopeClientCompositeErrorException scce) {
+            assertEquals(HttpStatus.BAD_REQUEST, scce.getStatusCode());
+            assertTrue(scce.hasException(SyncopeClientExceptionType.RequiredValuesMissing));
+        }
+    }
 }

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/ResourceTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/ResourceTestITCase.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/ResourceTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/ResourceTestITCase.java Fri Feb 22 16:31:19 2013
@@ -346,7 +346,7 @@ public class ResourceTestITCase extends 
 
     @Test
     public void delete() {
-        String resourceName = "ws-target-resource-delete";
+        String resourceName = "tobedeleted";
 
         ResourceTO resource = buildResourceTO(resourceName);
         Response response = resourceService.create(resource);
@@ -384,8 +384,30 @@ public class ResourceTestITCase extends 
     @Test
     public void read() {
         ResourceTO actual = resourceService.read("resource-testdb");
+        assertNotNull(actual);
+    }
 
+    @Test
+    public void issueSYNCOPE323() {
+        ResourceTO actual = resourceService.read("resource-testdb");
         assertNotNull(actual);
+
+        try {
+            createResource(resourceService, actual);
+            fail();
+        } catch (SyncopeClientCompositeErrorException scce) {
+            assertEquals(HttpStatus.CONFLICT, scce.getStatusCode());
+            assertTrue(scce.hasException(SyncopeClientExceptionType.EntityExists));
+        }
+
+        actual.setName(null);
+        try {
+            createResource(resourceService, actual);
+            fail();
+        } catch (SyncopeClientCompositeErrorException scce) {
+            assertEquals(HttpStatus.BAD_REQUEST, scce.getStatusCode());
+            assertTrue(scce.hasException(SyncopeClientExceptionType.RequiredValuesMissing));
+        }
     }
 
     private ResourceTO buildResourceTO(String resourceName) {

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/SchemaTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/SchemaTestITCase.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/SchemaTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/SchemaTestITCase.java Fri Feb 22 16:31:19 2013
@@ -164,8 +164,7 @@ public class SchemaTestITCase extends Ab
         SchemaTO schemaTO = schemaService.read(AttributableType.ROLE, SchemaType.NORMAL, "icon");
         assertNotNull(schemaTO);
 
-        schemaService.update(AttributableType.ROLE, SchemaType.NORMAL,
-                schemaTO.getName(), schemaTO);
+        schemaService.update(AttributableType.ROLE, SchemaType.NORMAL, schemaTO.getName(), schemaTO);
         SchemaTO updatedTO = schemaService.read(AttributableType.ROLE, SchemaType.NORMAL, "icon");
         assertEquals(schemaTO, updatedTO);
 
@@ -254,6 +253,29 @@ public class SchemaTestITCase extends Ab
         }
     }
 
+    @Test
+    public void issueSYNCOPE323() {
+        SchemaTO actual = schemaService.read(AttributableType.ROLE, SchemaType.NORMAL, "icon");
+        assertNotNull(actual);
+
+        try {
+            createSchema(AttributableType.ROLE, SchemaType.NORMAL, actual);
+            fail();
+        } catch (SyncopeClientCompositeErrorException scce) {
+            assertEquals(HttpStatus.CONFLICT, scce.getStatusCode());
+            assertTrue(scce.hasException(SyncopeClientExceptionType.EntityExists));
+        }
+
+        actual.setName(null);
+        try {
+            createSchema(AttributableType.ROLE, SchemaType.NORMAL, actual);
+            fail();
+        } catch (SyncopeClientCompositeErrorException scce) {
+            assertEquals(HttpStatus.BAD_REQUEST, scce.getStatusCode());
+            assertTrue(scce.hasException(SyncopeClientExceptionType.RequiredValuesMissing));
+        }
+    }
+
     private SchemaTO buildSchemaTO(final String name, final AttributeSchemaType type) {
         SchemaTO schemaTO = new SchemaTO();
         schemaTO.setName(name + getUUIDString());

Modified: syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/VirtualSchemaTestITCase.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/VirtualSchemaTestITCase.java?rev=1449107&r1=1449106&r2=1449107&view=diff
==============================================================================
--- syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/VirtualSchemaTestITCase.java (original)
+++ syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/VirtualSchemaTestITCase.java Fri Feb 22 16:31:19 2013
@@ -18,8 +18,11 @@
  */
 package org.apache.syncope.core.rest;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.util.List;
 
@@ -33,6 +36,7 @@ import org.apache.syncope.common.validat
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
+import org.springframework.http.HttpStatus;
 
 @FixMethodOrder(MethodSorters.JVM)
 public class VirtualSchemaTestITCase extends AbstractTest {
@@ -40,7 +44,8 @@ public class VirtualSchemaTestITCase ext
     @Test
     public void list() {
         @SuppressWarnings("unchecked")
-        List<VirtualSchemaTO> vSchemas = (List<VirtualSchemaTO>) schemaService.list(AttributableType.USER, SchemaType.VIRTUAL);
+        List<VirtualSchemaTO> vSchemas = (List<VirtualSchemaTO>) schemaService.list(AttributableType.USER,
+                SchemaType.VIRTUAL);
         assertFalse(vSchemas.isEmpty());
         for (VirtualSchemaTO vSchemaTO : vSchemas) {
             assertNotNull(vSchemaTO);
@@ -85,4 +90,27 @@ public class VirtualSchemaTestITCase ext
         }
         assertNotNull(t);
     }
+
+    @Test
+    public void issueSYNCOPE323() {
+        VirtualSchemaTO actual = schemaService.read(AttributableType.MEMBERSHIP, SchemaType.VIRTUAL, "mvirtualdata");
+        assertNotNull(actual);
+
+        try {
+            createSchema(AttributableType.MEMBERSHIP, SchemaType.VIRTUAL, actual);
+            fail();
+        } catch (SyncopeClientCompositeErrorException scce) {
+            assertEquals(HttpStatus.CONFLICT, scce.getStatusCode());
+            assertTrue(scce.hasException(SyncopeClientExceptionType.EntityExists));
+        }
+
+        actual.setName(null);
+        try {
+            createSchema(AttributableType.MEMBERSHIP, SchemaType.VIRTUAL, actual);
+            fail();
+        } catch (SyncopeClientCompositeErrorException scce) {
+            assertEquals(HttpStatus.BAD_REQUEST, scce.getStatusCode());
+            assertTrue(scce.hasException(SyncopeClientExceptionType.RequiredValuesMissing));
+        }
+    }
 }