public class JndiRmiClientInterceptor extends JndiObjectLocator implements MethodInterceptor, InitializingBean
MethodInterceptor
for accessing RMI services from JNDI.
Typically used for RMI-IIOP (CORBA), but can also be used for EJB home objects
(for example, a Stateful Session Bean home). In contrast to a plain JNDI lookup,
this accessor also performs narrowing through PortableRemoteObject.
With conventional RMI services, this invoker is typically used with the RMI service interface. Alternatively, this invoker can also proxy a remote RMI service with a matching non-RMI business interface, i.e. an interface that mirrors the RMI service methods but does not declare RemoteExceptions. In the latter case, RemoteExceptions thrown by the RMI stub will automatically get converted to Spring's unchecked RemoteAccessException.
The JNDI environment can be specified as "jndiEnvironment" property,
or be configured in a jndi.properties
file or as system properties.
For example:
<property name="jndiEnvironment"> <props> <prop key="java.naming.factory.initial">com.sun.jndi.cosnaming.CNCtxFactory</prop> <prop key="java.naming.provider.url">iiop://localhost:1050</prop> </props> </property>
JndiAccessor.setJndiTemplate(org.springframework.jndi.JndiTemplate)
,
JndiAccessor.setJndiEnvironment(java.util.Properties)
,
JndiObjectLocator.setJndiName(java.lang.String)
,
JndiRmiServiceExporter
,
JndiRmiProxyFactoryBean
,
RemoteAccessException
,
RemoteException
,
Remote
,
PortableRemoteObject.narrow(java.lang.Object, java.lang.Class)
CONTAINER_PREFIX
logger
Constructor and Description |
---|
JndiRmiClientInterceptor() |
Modifier and Type | Method and Description |
---|---|
void |
afterPropertiesSet()
Invoked by a BeanFactory after it has set all bean properties supplied
(and satisfied BeanFactoryAware and ApplicationContextAware).
|
protected RemoteInvocation |
createRemoteInvocation(MethodInvocation methodInvocation)
Create a new RemoteInvocation object for the given AOP method invocation.
|
protected Object |
doInvoke(MethodInvocation invocation,
Object stub)
Perform the given invocation on the given RMI stub.
|
protected Object |
doInvoke(MethodInvocation methodInvocation,
RmiInvocationHandler invocationHandler)
Apply the given AOP method invocation to the given
RmiInvocationHandler . |
RemoteInvocationFactory |
getRemoteInvocationFactory()
Return the RemoteInvocationFactory used by this accessor.
|
Class |
getServiceInterface()
Return the interface of the service to access.
|
protected Object |
getStub()
Return the RMI stub to use.
|
Object |
invoke(MethodInvocation invocation)
Fetches an RMI stub and delegates to
doInvoke(org.aopalliance.intercept.MethodInvocation, java.lang.Object) . |
protected boolean |
isConnectFailure(RemoteException ex)
Determine whether the given RMI exception indicates a connect failure.
|
protected boolean |
isConnectFailure(SystemException ex)
Determine whether the given CORBA exception indicates a connect failure.
|
protected Object |
lookupStub()
Create the RMI stub, typically by looking it up.
|
void |
prepare()
Fetches the RMI stub on startup, if necessary.
|
protected Object |
refreshAndRetry(MethodInvocation invocation)
Refresh the RMI stub and retry the given invocation.
|
void |
setCacheStub(boolean cacheStub)
Set whether to cache the RMI stub once it has been located.
|
void |
setLookupStubOnStartup(boolean lookupStubOnStartup)
Set whether to look up the RMI stub on startup.
|
void |
setRefreshStubOnConnectFailure(boolean refreshStubOnConnectFailure)
Set whether to refresh the RMI stub on connect failure.
|
void |
setRemoteInvocationFactory(RemoteInvocationFactory remoteInvocationFactory)
Set the RemoteInvocationFactory to use for this accessor.
|
void |
setServiceInterface(Class serviceInterface)
Set the interface of the service to access.
|
getExpectedType, getJndiName, lookup, setExpectedType, setJndiName
convertJndiName, isResourceRef, lookup, lookup, setResourceRef
getJndiEnvironment, getJndiTemplate, setJndiEnvironment, setJndiTemplate
public void setServiceInterface(Class serviceInterface)
Typically required to be able to create a suitable service proxy, but can also be optional if the lookup returns a typed stub.
public Class getServiceInterface()
public void setRemoteInvocationFactory(RemoteInvocationFactory remoteInvocationFactory)
DefaultRemoteInvocationFactory
.
A custom invocation factory can add further context information to the invocation, for example user credentials.
public RemoteInvocationFactory getRemoteInvocationFactory()
public void setLookupStubOnStartup(boolean lookupStubOnStartup)
Can be turned off to allow for late start of the RMI server. In this case, the RMI stub will be fetched on first access.
setCacheStub(boolean)
public void setCacheStub(boolean cacheStub)
Can be turned off to allow for hot restart of the RMI server. In this case, the RMI stub will be fetched for each invocation.
setLookupStubOnStartup(boolean)
public void setRefreshStubOnConnectFailure(boolean refreshStubOnConnectFailure)
Can be turned on to allow for hot restart of the RMI server. If a cached RMI stub throws an RMI exception that indicates a remote connect failure, a fresh proxy will be fetched and the invocation will be retried.
public void afterPropertiesSet() throws NamingException
InitializingBean
This method allows the bean instance to perform initialization only possible when all bean properties have been set and to throw an exception in the event of misconfiguration.
afterPropertiesSet
in interface InitializingBean
afterPropertiesSet
in class JndiObjectLocator
NamingException
public void prepare() throws RemoteLookupFailureException
RemoteLookupFailureException
- if RMI stub creation failedsetLookupStubOnStartup(boolean)
,
lookupStub()
protected Object lookupStub() throws RemoteLookupFailureException
Called on interceptor initialization if "cacheStub" is "true";
else called for each invocation by getStub()
.
The default implementation retrieves the service from the JNDI environment. This can be overridden in subclasses.
RemoteLookupFailureException
- if RMI stub creation failedsetCacheStub(boolean)
,
JndiObjectLocator.lookup()
protected Object getStub() throws NamingException, RemoteLookupFailureException
The default implementation returns the stub created on initialization,
if any. Else, it invokes lookupStub()
to get a new stub for
each invocation. This can be overridden in subclasses, for example in
order to cache a stub for a given amount of time before recreating it,
or to test the stub whether it is still alive.
NamingException
- if stub creation failedRemoteLookupFailureException
- if RMI stub creation failedpublic Object invoke(MethodInvocation invocation) throws Throwable
doInvoke(org.aopalliance.intercept.MethodInvocation, java.lang.Object)
.
If configured to refresh on connect failure, it will call
refreshAndRetry(org.aopalliance.intercept.MethodInvocation)
on corresponding RMI exceptions.protected boolean isConnectFailure(RemoteException ex)
The default implementation delegates to
RmiClientInterceptorUtils.isConnectFailure(java.rmi.RemoteException)
.
ex
- the RMI exception to checkprotected boolean isConnectFailure(SystemException ex)
The default implementation checks for CORBA's
OBJECT_NOT_EXIST
exception.
ex
- the RMI exception to checkprotected Object refreshAndRetry(MethodInvocation invocation) throws Throwable
invocation
- the AOP method invocationThrowable
- in case of invocation failureinvoke(org.aopalliance.intercept.MethodInvocation)
protected Object doInvoke(MethodInvocation invocation, Object stub) throws Throwable
invocation
- the AOP method invocationstub
- the RMI stub to invokeThrowable
- in case of invocation failureprotected Object doInvoke(MethodInvocation methodInvocation, RmiInvocationHandler invocationHandler) throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException
RmiInvocationHandler
.
The default implementation delegates to createRemoteInvocation(org.aopalliance.intercept.MethodInvocation)
.
methodInvocation
- the current AOP method invocationinvocationHandler
- the RmiInvocationHandler to apply the invocation toRemoteException
- in case of communication errorsNoSuchMethodException
- if the method name could not be resolvedIllegalAccessException
- if the method could not be accessedInvocationTargetException
- if the method invocation resulted in an exceptionRemoteInvocation
protected RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation)
The default implementation delegates to the configured
RemoteInvocationFactory
.
This can be overridden in subclasses in order to provide custom RemoteInvocation
subclasses, containing additional invocation parameters (e.g. user credentials).
Note that it is preferable to build a custom RemoteInvocationFactory as a reusable strategy, instead of overriding this method.
methodInvocation
- the current AOP method invocationRemoteInvocationFactory.createRemoteInvocation(org.aopalliance.intercept.MethodInvocation)