mirror of
https://gitee.com/jmix/cuba.git
synced 2024-12-02 19:27:57 +08:00
Refs #1004 Rework remote exception handling
This commit is contained in:
parent
ee29619411
commit
17084c8999
@ -60,6 +60,11 @@ public class TestingServiceBean implements TestingService {
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String executeWithException() throws TestException {
|
||||
throw new TestException("an error");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearScheduledTasks() {
|
||||
Transaction tx = persistence.createTransaction();
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
package com.haulmont.cuba.core.app;
|
||||
|
||||
import com.haulmont.cuba.core.global.SupportedByClient;
|
||||
|
||||
/**
|
||||
* Service interface for integration testing. Don't use it in application code!
|
||||
*
|
||||
@ -23,8 +25,18 @@ public interface TestingService {
|
||||
|
||||
boolean primitiveParameters(boolean b, int i, long l, double d);
|
||||
|
||||
String executeWithException() throws TestException;
|
||||
|
||||
/**
|
||||
* Warning! Removes all scheduled tasks from the database!
|
||||
*/
|
||||
void clearScheduledTasks();
|
||||
|
||||
@SupportedByClient
|
||||
public static class TestException extends Exception {
|
||||
|
||||
public TestException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import com.haulmont.cuba.core.sys.ClassesInfo;
|
||||
import com.haulmont.cuba.security.entity.PermissionType;
|
||||
|
||||
/**
|
||||
@ -15,14 +14,11 @@ import com.haulmont.cuba.security.entity.PermissionType;
|
||||
*
|
||||
* @author krivopustov
|
||||
*/
|
||||
@SupportedByClient
|
||||
public class AccessDeniedException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = -3097861878301424338L;
|
||||
|
||||
static {
|
||||
ClassesInfo.addClientSupported(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
private PermissionType type;
|
||||
|
||||
private String target;
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import com.haulmont.cuba.core.sys.ClassesInfo;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@ -18,7 +17,7 @@ import java.util.List;
|
||||
/**
|
||||
* Exception that returns to clients from the middleware. Contains the information about the whole server-side
|
||||
* exception chain in the <code>Cause</code> objects list. Actual exception instances are included only if they
|
||||
* explicitly made available for the clients (registered in {@link ClassesInfo}).
|
||||
* explicitly declared as available for the clients (annotated with {@link SupportedByClient}).
|
||||
*
|
||||
* <p>$Id$</p>
|
||||
*
|
||||
@ -35,7 +34,7 @@ public class RemoteException extends RuntimeException {
|
||||
public Cause(Throwable throwable) {
|
||||
className = throwable.getClass().getName();
|
||||
message = throwable.getMessage();
|
||||
if (ClassesInfo.isClientSupported(throwable.getClass()))
|
||||
if (throwable.getClass().getAnnotation(SupportedByClient.class) != null)
|
||||
this.throwable = throwable;
|
||||
}
|
||||
|
||||
@ -72,6 +71,19 @@ public class RemoteException extends RuntimeException {
|
||||
return Collections.unmodifiableList(causes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return First exception in the causes list if it is checked, null otherwise
|
||||
*/
|
||||
public Exception getFirstCheckedException() {
|
||||
if (!causes.isEmpty()) {
|
||||
Throwable t = causes.get(0).getThrowable();
|
||||
if (t != null && !(t instanceof RuntimeException) && !(t instanceof Error)) {
|
||||
return (Exception) t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("RemoteException:");
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Haulmont Technology Ltd. All Rights Reserved.
|
||||
* Haulmont Technology proprietary and confidential.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation that marks a class as available on the client side.
|
||||
*
|
||||
* <p>$Id$</p>
|
||||
*
|
||||
* @author krivopustov
|
||||
*/
|
||||
@Target({java.lang.annotation.ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SupportedByClient {
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Haulmont Technology Ltd. All Rights Reserved.
|
||||
* Haulmont Technology proprietary and confidential.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.core.sys;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class that provides information about classes availability for different application layers.
|
||||
*
|
||||
* <p>$Id$</p>
|
||||
*
|
||||
* @author krivopustov
|
||||
*/
|
||||
public class ClassesInfo {
|
||||
|
||||
private static List<Class> clientSupported = new ArrayList<Class>();
|
||||
|
||||
/**
|
||||
* Register a class as available for the client layer.
|
||||
* @param aClass class
|
||||
*/
|
||||
public static synchronized void addClientSupported(Class aClass) {
|
||||
if (!clientSupported.contains(aClass))
|
||||
clientSupported.add(aClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the class is available for the client layer.
|
||||
* @param aClass class
|
||||
* @return true if available
|
||||
*/
|
||||
public static synchronized boolean isClientSupported(Class aClass) {
|
||||
return clientSupported.contains(aClass);
|
||||
}
|
||||
}
|
@ -6,7 +6,11 @@
|
||||
|
||||
package com.haulmont.cuba.core.sys.remoting;
|
||||
|
||||
import com.haulmont.cuba.core.global.RemoteException;
|
||||
import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean;
|
||||
import org.springframework.remoting.support.RemoteInvocationResult;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
/**
|
||||
* <p>$Id$</p>
|
||||
@ -23,4 +27,19 @@ public class HttpServiceProxy extends HttpInvokerProxyFactoryBean {
|
||||
executor.setBeanClassLoader(getBeanClassLoader());
|
||||
setHttpInvokerRequestExecutor(executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object recreateRemoteInvocationResult(RemoteInvocationResult result) throws Throwable {
|
||||
Throwable throwable = result.getException();
|
||||
if (throwable != null) {
|
||||
if (throwable instanceof InvocationTargetException)
|
||||
throwable = ((InvocationTargetException) throwable).getTargetException();
|
||||
if (throwable instanceof RemoteException) {
|
||||
Exception exception = ((RemoteException) throwable).getFirstCheckedException();
|
||||
if (exception != null) // This is a checked exception declared in a service method
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
return super.recreateRemoteInvocationResult(result);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
package com.haulmont.cuba.security.global;
|
||||
|
||||
import com.haulmont.cuba.core.sys.ClassesInfo;
|
||||
import com.haulmont.cuba.core.global.SupportedByClient;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@ -16,14 +16,11 @@ import java.util.UUID;
|
||||
*
|
||||
* @author krivopustov
|
||||
*/
|
||||
@SupportedByClient
|
||||
public class NoUserSessionException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 4820628023682230319L;
|
||||
|
||||
static {
|
||||
ClassesInfo.addClientSupported(NoUserSessionException.class);
|
||||
}
|
||||
|
||||
public NoUserSessionException(UUID sessionId) {
|
||||
super(String.format("User session not found: %s", sessionId.toString()));
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
package com.haulmont.cuba.web.sys.remoting;
|
||||
|
||||
import com.haulmont.cuba.core.global.RemoteException;
|
||||
import com.haulmont.cuba.core.sys.AppContext;
|
||||
import com.haulmont.cuba.core.sys.Deserializer;
|
||||
import com.haulmont.cuba.core.sys.remoting.LocalServiceDirectory;
|
||||
@ -17,9 +18,6 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.remoting.support.RemoteAccessor;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
@ -116,6 +114,11 @@ public class LocalServiceProxy extends RemoteAccessor implements FactoryBean<Obj
|
||||
// don't use SerializationUtils.deserialize() here to avoid ClassNotFoundException
|
||||
if (result.getException() != null) {
|
||||
Throwable t = (Throwable) Deserializer.deserialize(result.getException());
|
||||
if (t instanceof RemoteException) {
|
||||
Exception exception = ((RemoteException) t).getFirstCheckedException();
|
||||
if (exception != null) // This is a checked exception declared in a service method
|
||||
throw exception;
|
||||
}
|
||||
throw t;
|
||||
} else {
|
||||
Object data = Deserializer.deserialize(result.getData());
|
||||
|
Loading…
Reference in New Issue
Block a user