Académique Documents
Professionnel Documents
Culture Documents
Topics
Professional Open Source™
Invoker implementations
– RMI/JRMP Invoker
1
JBoss and Detached Invokers
Professional Open Source™
Port 1234
RemoteInvoker
RemoteInvoker
JMX
JMX Microkernel
Client JVM
EJB Container MBean
Typed
Microkernel
Interface Invocation
011101010101
Client
Client RemoteInvoker
RemoteInvoker
Port 4321
Service MBean
Client Proxy
Client JVM
Microkernel
Microkernel
01010110101001
Client
Client Invoker
Invoker
java.lang.reflect.InvocationHandler
java.lang.reflect.InvocationHandler javax.management.MBeanServer
javax.management.MBeanServer
Object Object
Objectinvoke(
invoke( ObjectName
ObjectNamename,
name,String
StringoperationName,
Objectinvoke(Object
invoke(Objectproxy,
proxy,Method
Methodmethod,
method,Object[]
Object[]args)
args) operationName,
Object[]
Object[]params,
params,String[]
String[]signature)
signature)
2
The Message
Professional Open Source™
Interceptors
Professional Open Source™
3
Distributed Invokers
Professional Open Source™
A
A invoker
invoker extends
extends Remote
Remote
package
packageorg.jboss.invocation;
org.jboss.invocation; Even
Even ifif the
the implementation
implementation
is
is local
local
public
publicinterface
interfaceInvoker
Invokerextends
extendsRemote
Remote{{
/**
/**
**TheTheinvoke
invokewith
withan
anInvocation
InvocationObject
Object
**thethedelegate
delegatecan
canhandle
handlenetwork
networkprotocols
protocolsononbehalf
behalfofofproxies
proxies(proxies
(proxiesdelegate
delegatetotothese
thesepuppies)
puppies)
** We Weprovide
providedefault
defaultimplemenations
implemenationswith withJRMP/Local/Clustered
JRMP/Local/Clusteredinvokers.
invokers.
** TheThedelegates
delegatesare
arenot
nottied
tiedtotoaatype
typeofofinvocation
invocation(EJB
(EJBororgeneric
genericRMI).
RMI).
**
**@param
@paraminvocation
invocation AApointer
pointertotothetheinvocation
invocationobject
object
**
**@return
@return Return
Returnvalue
valueofofmethod
methodinvocation.
invocation.
**
**@throws
@throwsException
Exception Failed
Failedtotoinvoke
invokemethod.
method.
*/*/
public
publicObject
Objectinvoke(Invocation
invoke(Invocationinvocation)
invocation) throws
throwsException;
Exception;
}}
JRMPInvoker (1/2)
Professional Open Source™
org.jboss.invocation.jrmp.server.JRMPInvoker
org.jboss.invocation.jrmp.server.JRMPInvoker
/**
/**
**TheTheJRMPInvoker
JRMPInvokerisisananRMI
RMIimplementation
implementationthat
thatcan
cangenerate
generateInvocations
Invocations
**from
fromRMI/JRMP
RMI/JRMPinto
intothe
theJMX
JMXbase.
base.
*/*/
public
publicclass
classJRMPInvoker
JRMPInvokerextends
extendsRemoteServer
RemoteServer
implements
implementsInvoker,
Invoker,JRMPInvokerMBean,
JRMPInvokerMBean, MBeanRegistration
MBeanRegistration{{
/**
/**An
Anoptional
optionalcustom
customclient
clientsocket
socketfactory
factory*/*/
protected
protectedRMIClientSocketFactory
RMIClientSocketFactoryclientSocketFactory;
clientSocketFactory;
/**
/**An
Anoptional
optionalcustom
customserver
serversocket
socketfactory
factory*/*/
protected
protectedRMIServerSocketFactory
RMIServerSocketFactoryserverSocketFactory;
serverSocketFactory;
/**
/**The
Theclass
classname
nameofofthe
theoptional
optionalcustom
customclient
clientsocket
socketfactory
factory*/*/
protected
protectedString
StringclientSocketFactoryName;
clientSocketFactoryName;
/**
/**The
Theclass
classname
nameofofthe
theoptional
optionalcustom
customserver
serversocket
socketfactory
factory*/*/
protected
protectedString
StringserverSocketFactoryName;
serverSocketFactoryName;
/**
/**The
Theaddress
addresstotobind
bindthe
thermi
rmiport
porton
on*/*/
protected
protectedString
StringserverAddress;
serverAddress;
/**
/**The
Thename
nameofofthe
thesecurity
securitydomain
domaintotouse
usewith
withserver
serversockets
socketsthat
thatsupport
supportSSL
SSL*/*/
protected
protectedString
StringsslDomain;
sslDomain;
4
JRMPInvoker (2/2)
Professional Open Source™
org.jboss.invocation.jrmp.server.JRMPInvoker
org.jboss.invocation.jrmp.server.JRMPInvoker
/**
/**
**Invoke
InvokeaaRemote
Remoteinterface
interfacemethod.
method.
*/*/
public
publicObject
Objectinvoke(Invocation
invoke(Invocationinvocation)
invocation)throws
throwsException
Exception{{
ClassLoader
ClassLoaderoldCl
oldCl==Thread.currentThread().getContextClassLoader();
Thread.currentThread().getContextClassLoader();
ObjectName
ObjectNamembean
mbean==null;
null;
try
try{{
////Deserialize
Deserializethe
thetransaction
transactionififititis
isthere
there
MarshalledInvocation
MarshalledInvocationmi mi==(MarshalledInvocation)
(MarshalledInvocation)invocation;
invocation;
Invocation
Invocation object
invocation.setTransaction(importTPC(mi.getTransactionPropagationContext()));
invocation.setTransaction(importTPC(mi.getTransactionPropagationContext())); object carries
carries the
the
target
target name
name (JMX
(JMX
mbean
mbean==(ObjectName)
(ObjectName)Registry.lookup(invocation.getObjectName());
Registry.lookup(invocation.getObjectName()); ObjectName)
ObjectName)
////The
Thecl
clon
onthe
thethread
threadshould
shouldbe
beset
setin
inanother
anotherinterceptor
interceptor
Object
Objectobj
obj==support.getServer().invoke(mbean,
support.getServer().invoke(mbean,"invoke",
"invoke",
new Object[] {invocation}, Send
new Object[] {invocation}, Send thethe invocation
invocation to
to
Invocation.INVOKE_SIGNATURE); the
Invocation.INVOKE_SIGNATURE); the target
target through
through the
the
return
returnnew
newMarshalledObject(obj);
MarshalledObject(obj); microkernel.
microkernel.
}} finally {
finally {
currentThread.setContextClassLoader(oldCl);
currentThread.setContextClassLoader(oldCl);
}}
Any MBean can expose an interface for remote invocations using proxy
factory services
You can easily add your own proxy factories following the pattern illustrated in
these two services
5
JRMPProxyFactory
Professional Open Source™
A general service for exposing a proxy RPC interface for any MBean
over any transport.
– Has nothing to do with RMI/JRMP, just a historic name
JRMPProxyFactoryMBean
Professional Open Source™
org.jboss.invocation.jrmp.server.
org.jboss.invocation.jrmp.server.JRMPProxyFactoryMBean
JRMPProxyFactoryMBean
public
publicinterface
interfaceJRMPProxyFactoryMBean
JRMPProxyFactoryMBeanextends
extendsServiceMBean
ServiceMBean Detached
Detached invoker
invoker service
service
{{
handling
handling transport
transport
public
publicObjectName
ObjectNamegetInvokerName();
getInvokerName();
public
publicvoid
voidsetInvokerName(ObjectName
setInvokerName(ObjectNamejmxInvokerName);
jmxInvokerName);
public
publicObjectName
ObjectNamegetTargetName();
getTargetName(); Target
Target MBean
MBean
public
publicvoid
voidsetTargetName(ObjectName
setTargetName(ObjectNametargetName);
targetName); invocations
invocations will
will be
be
dispatched
dispatched to
to
public
publicString
StringgetJndiName();
getJndiName();
public
publicvoid
voidsetJndiName(String
setJndiName(StringjndiName);
jndiName);
public
publicClass[]
Class[]getExportedInterfaces();
getExportedInterfaces(); RPC
RPC interfaces
interfaces client
client
public
publicvoid
voidsetExportedInterfaces(Class[]
setExportedInterfaces(Class[]exportedInterface);
exportedInterface); will
will see
see
public
publicElement
ElementgetClientInterceptors();
getClientInterceptors();
public
publicvoid
voidsetClientInterceptors(Element
setClientInterceptors(Elementconfig)
config)throws
throwsException;
Exception;
public
publicObject
ObjectgetProxy();
getProxy(); Client
Client proxy
proxy interceptor
interceptor
}} stack
stack
6
JRMPProxyFactory Example
Professional Open Source™
<!--
<!--The
TheJRMP
JRMPinvoker
invokerproxy
proxyconfiguration
configurationfor
forthe
theInvokerAdaptorService
InvokerAdaptorService-->
-->
<mbean
<mbeancode="org.jboss.invocation.jrmp.server.JRMPProxyFactory"
code="org.jboss.invocation.jrmp.server.JRMPProxyFactory"
name="jboss.jmx:type=adaptor,name=Invoker,protocol=jrmp,service=proxyFactory">
name="jboss.jmx:type=adaptor,name=Invoker,protocol=jrmp,service=proxyFactory">
<!--
<!--Use
Usethe
thestandard
standardJRMPInvoker
JRMPInvokerfromfromconf/jboss-service.xml
conf/jboss-service.xml-->
-->
<depends
<dependsoptional-attribute-name="InvokerName">jboss:service=invoker,type=jrmp</depends>
optional-attribute-name="InvokerName">jboss:service=invoker,type=jrmp</depends>
<!--
<!-- The target MBean is the InvokerAdaptorService configured below-->
The target MBean is the InvokerAdaptorService configured below -->
<depends
<dependsoptional-attribute-name="TargetName">jboss.jmx:type=adaptor,name=Invoker</depends>
optional-attribute-name="TargetName">jboss.jmx:type=adaptor,name=Invoker</depends>
<!--
<!--Where
Whereto tobind
bindthe
theRMIAdaptor
RMIAdaptorproxy
proxy-->
-->
<attribute
<attributename="JndiName">jmx/invoker/RMIAdaptor</attribute>
name="JndiName">jmx/invoker/RMIAdaptor</attribute>
<!--
<!--The
TheRMI
RMIcompabitle
compabitleMBeanServer
MBeanServerinterface
interface-->
-->
<attribute
<attributename="ExportedInterfaces">org.jboss.jmx.adaptor.rmi.RMIAdaptor,
name="ExportedInterfaces">org.jboss.jmx.adaptor.rmi.RMIAdaptor,
org.jboss.jmx.adaptor.rmi.RMIAdaptorExt
org.jboss.jmx.adaptor.rmi.RMIAdaptorExt
</attribute>
</attribute>
<attribute
<attributename="ClientInterceptors">
name="ClientInterceptors">
<interceptors>
<interceptors>
<interceptor>org.jboss.proxy.ClientMethodInterceptor</interceptor>
<interceptor>org.jboss.proxy.ClientMethodInterceptor</interceptor>
<interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
<interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
<interceptor>org.jboss.jmx.connector.invoker.client.InvokerAdaptorClientInterceptor</interceptor>
<interceptor>org.jboss.jmx.connector.invoker.client.InvokerAdaptorClientInterceptor</interceptor>
<interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
<interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
</interceptors>
</interceptors>
</attribute>
</attribute>
</mbean>
</mbean>
Interceptor
Professional Open Source™
org.jboss.ejb.Interceptor
org.jboss.ejb.Interceptor
public
publicinterface
interfaceInterceptor
Interceptorextends
extendsContainerPlugin
ContainerPlugin
{{
public
publicvoid
voidsetNext(Interceptor
setNext(Interceptorinterceptor);
interceptor);
public
publicInterceptor
InterceptorgetNext();
getNext();
public
publicObject
ObjectinvokeHome(Invocation
invokeHome(Invocationmi)
mi)throws
throwsException;
Exception;
public
publicObject
Objectinvoke(Invocation
invoke(Invocationmi)
mi)throws
throwsException;
Exception;
}}
Each
Each implements
implements Interceptor
Interceptor
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Relation
Security
Relation
Security
Cache
Cache
Lock
Lock
Call
Call
7
Interceptors
Professional Open Source™
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Relation
Security
Includes all
Relation
Security
Cache
Cache
Lock
Lock
Call
Call
transactional
and persistence
Transaction
Transaction
Security
Security
No
Cache
Cache
Lock
Lock
Call
Call
persistence
Interceptors
Professional Open Source™
8
Specifying the Interceptor Stack
Professional Open Source™
standardjboss.xml
standardjboss.xml or
orjboss.xml
jboss.xml
<jboss>
<jboss>
<enforce-ejb-restrictions>false</enforce-ejb-restrictions>
<enforce-ejb-restrictions>false</enforce-ejb-restrictions>
<container-configurations>
<container-configurations>
<container-configuration>
<container-configuration>
<container-name>Standard
<container-name>StandardCMP CMP2.x
2.xEntityBean</container-name>
EntityBean</container-name>
<call-logging>false</call-logging>
<call-logging>false</call-logging>
<container-invoker>org.jboss.proxy.ejb.ProxyFactory</container-invoker>
<container-invoker>org.jboss.proxy.ejb.ProxyFactory</container-invoker>
<container-interceptors>
<container-interceptors>
<interceptor>org.jboss.ejb.plugins.LogInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.LogInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.SecurityInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.SecurityInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.TxInterceptorCMT</interceptor>
<interceptor>org.jboss.ejb.plugins.TxInterceptorCMT</interceptor>
<interceptor
<interceptormetricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptor</interceptor>
metricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.EntityCreationInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.EntityCreationInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.EntityLockInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.EntityLockInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.EntityInstanceInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.EntityInstanceInterceptor</interceptor>
<interceptor>org.jboss.resource.connectionmanager.CachedConnectionInterceptor</interceptor>
<interceptor>org.jboss.resource.connectionmanager.CachedConnectionInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.EntitySynchronizationInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.EntitySynchronizationInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.cmp.jdbc.JDBCRelationInterceptor</interceptor>
<interceptor>org.jboss.ejb.plugins.cmp.jdbc.JDBCRelationInterceptor</interceptor>
</container-interceptors>
</container-interceptors>
An EJB Container
Professional Open Source™
Bean
Bean CMP
CMP
Cache
Cache
Lock
Lock Engine
Engine
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
9
An Entity Bean Creation Walkthrough
Professional Open Source™
Deployment
– EJB Deployer
– Container configuration
– EJB home proxy creation and export
Deployment
Professional Open Source™
Deployer Container
Factory
/deploy
10
Deployment
Professional Open Source™
Deployer Container
Factory Container
/deploy JNDI
HomeProxy
Log Interceptor
Professional Open Source™
1- Logging
– Log the call and what was in it
• The arguments
• The method name
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
Log
Call
Log
Call
Invocation
11
Security Interceptor
Professional Open Source™
2-Security
– Enforces J2EE declarative security
• Authentication
• Role-based permissions
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
Log
Call
Log
Call
Invocation
Security Interceptor
Professional Open Source™
org.jboss.ejb.plugins.SecurityInterceptor
org.jboss.ejb.plugins.SecurityInterceptor
/**
/**The
TheSecurityInterceptor
SecurityInterceptorisiswhere
wherethetheEJB
EJB2.0
2.0declarative
declarativesecurity
securitymodel
model
** isisenforced.
enforced.ThisThisisiswhere
wherethethecaller
calleridentity
identitypropagation
propagationisiscontrolled
controlledasaswell.
well.*/*/
public
publicclass classSecurityInterceptor
SecurityInterceptorextends
extendsAbstractInterceptor
AbstractInterceptor
{{
protected
protectedAuthenticationManager
AuthenticationManagersecurityManager;
securityManager;
protected
protectedRealmMapping
RealmMappingrealmMapping;
realmMapping;
protected Interfaces
Interfacesimplemented
implemented
protectedPrincipal
PrincipalrunAsRole;
runAsRole;
by
bythe
thesecurity
securitymanager.
manager.
public
publicvoid voidsetContainer(Container
setContainer(Containercontainer)
container)
{{
super.setContainer(container);
super.setContainer(container);
if(if(container
container!=!=null
null))
{{
BeanMetaData
BeanMetaDatabeanMetaData
beanMetaData==container.getBeanMetaData();
container.getBeanMetaData();
SecurityIdentityMetaData
SecurityIdentityMetaDatasecMetaData
secMetaData==beanMetaData.getSecurityIdentityMetaData();
beanMetaData.getSecurityIdentityMetaData();
if(
if(secMetaData
secMetaData!=!=nullnull&&
&&secMetaData.getUseCallerIdentity()
secMetaData.getUseCallerIdentity()== ==false
false))
{{
String
StringroleName
roleName==secMetaData.getRunAsRoleName();
secMetaData.getRunAsRoleName();
runAsRole
runAsRole==new newSimplePrincipal(roleName);
SimplePrincipal(roleName); Metadata
Metadataisis
}} retrieved
retrieved
securityManager
securityManager==container.getSecurityManager();
container.getSecurityManager(); from
fromthe
thecontainer.
container.
realmMapping
realmMapping==container.getRealmMapping();
container.getRealmMapping();
}}
12
Security Interceptor: Run-As
Professional Open Source™
org.jboss.ejb.plugins.SecurityInterceptor
org.jboss.ejb.plugins.SecurityInterceptor
public
publicObject
Objectinvoke(Invocation
invoke(Invocationmi)
mi)throws
throwsException
Exception
{{
////Authenticate
Authenticatethe
thesubject
subjectand
andapply
applyany
anydeclarative
declarativesecurity
securitychecks
checks
checkSecurityAssociation(mi,
checkSecurityAssociation(mi,false);
false);
Authentication
Authentication and
and authorization
authorization
/*/*IfIfaarun-as
run-asrole
rolewas
wasspecified,
specified,push
pushititso
sothat
thatany
anycalls
callsmade
made is
is done
done here.
here.
**by bythis
thisbean
beanwill
willhave
havethe
therunAsRole
runAsRoleavailable
availablefor
fordeclarative
declarative
**security
securitychecks.
checks.
*/*/
if(if(runAsRole
runAsRole!=!=null
null))
SecurityAssociation.pushRunAsRole(runAsRole);
SecurityAssociation.pushRunAsRole(runAsRole);
try
try{{
Object IfIf<run-as>
<run-as>element
elementhas
hasbeen
beenset,
set,
ObjectreturnValue
returnValue==getNext().invoke(mi);
getNext().invoke(mi);
return push
pushandandpop
popthe
therun-as
run-asrole
roleinto
into
returnreturnValue;
returnValue; thread
threadlocal.
local.
}}
finally
finally{{
if(
if(runAsRole
runAsRole!=!=null
null))
SecurityAssociation.popRunAsRole();
SecurityAssociation.popRunAsRole();
}}
org.jboss.ejb.plugins.SecurityInterceptor
org.jboss.ejb.plugins.SecurityInterceptor
/**
/**TheTheEJB EJB2.0
2.0declarative
declarativesecurity
securityalgorithm:
algorithm:
** 1.1.Authenticate
Authenticatethe thecaller
callerusing
usingthetheprincipal
principaland
andcredentials
credentialsininthe
theMethodInvocation
MethodInvocation
** 2.2.Validate
Validateaccess
accesstotothe
themethod
methodby bychecking
checkingthetheprincipal's
principal'sroles
rolesagainst
against
** those thoserequired
requiredtotoaccess
accessthethemethod.
method.
*/*/
private
privatevoid voidcheckSecurityAssociation(Invocation
checkSecurityAssociation(Invocationmi, mi,boolean
booleanhome)
home) throws
throwsException
Exception
{{
Principal
Principalprincipal
principal==mi.getPrincipal();
mi.getPrincipal(); The
TheInvocation
Invocationobject
object
Object
Objectcredential
credential==mi.getCredential();
mi.getCredential(); carries
carriesthe
thesecurity
securitycontext.
context.
////IfIfthere is no security manager then there is no authentication
there is no security manager then there is no authentication required required
ifif(securityManager
(securityManager== ==null)
null){{
////Allow
Allowfor
forthe
theprogatation
progatationofofcaller
callerinfo
infototoother
otherbeans
beans
SecurityAssociation.setPrincipal(
SecurityAssociation.setPrincipal(principal
principal););
SecurityAssociation.setCredential(
SecurityAssociation.setCredential(credential
credential););
return; Authentication
Authenticationcheck
check
return; using
}} usingsecurity
securitymanager
manager
(AuthenticationManager
(AuthenticationManager
////Check
Checkthe thesecurity
securityinfo
infofrom
fromthe
themethod
methodinvocation
invocation interface).
interface).
ifif(securityManager.isValid(principal,
(securityManager.isValid(principal,credential)
credential)====false)
false) {{
SecurityException e = new SecurityException(msg);
SecurityException e = new SecurityException(msg);
throw
thrownewnewRemoteException("checkSecurityAssociation",
RemoteException("checkSecurityAssociation",e); e);
}…}…
13
Security Interceptor: Authorization
Professional Open Source™
org.jboss.ejb.plugins.SecurityInterceptor
org.jboss.ejb.plugins.SecurityInterceptor
......
/*/*IfIfthe
themethod
methodhas hasno
noassigned
assignedroles
rolesororthe
theuser
userdoes
doesnot
nothave
haveatat
least
leastone oneofofthe
theroles
rolesthen
thenaccess
accessisisdenied.
denied.*/*/
else
elseifif(realmMapping.doesUserHaveRole(principal,
(realmMapping.doesUserHaveRole(principal,methodRoles)
methodRoles)== ==false
false))
{{
String
Stringmethod
method==mi.getMethod().getName();
mi.getMethod().getName();
Set
SetuserRoles
userRoles==realmMapping.getUserRoles(principal);
realmMapping.getUserRoles(principal); Authorization.
Authorization.
String
Stringmsgmsg=="Insufficient
"Insufficientmethod
methodpermissions,
permissions,principal="+principal
principal="+principal
++",",method="+method+",
method="+method+",interface="+iface
interface="+iface
++",",requiredRoles="+methodRoles+",
requiredRoles="+methodRoles+",principalRoles="+userRoles;
principalRoles="+userRoles;
log.error(msg);
log.error(msg);
SecurityException e = new SecurityException(msg);
SecurityException e = new SecurityException(msg);
throw
thrownew newEJBException("checkSecurityAssociation",
EJBException("checkSecurityAssociation",e); e);
}}
}}
Transaction Interceptor
Professional Open Source™
3- Transaction (CMT)
– Does the methodA require a Tx?
– If so start one, if not maybe suspend it
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
Log
Call
Log
Call
Invocation
14
TXInterceptorCMT: Deadlock Recovery (1/5)
Professional Open Source™
org.jboss.ejb.plugins.TXInterceptorCMT
org.jboss.ejb.plugins.TXInterceptorCMT
public
publicclass
classTxInterceptorCMT
TxInterceptorCMTextends
extendsAbstractTxInterceptor
AbstractTxInterceptor{{
public
publicstatic
staticint
intMAX_RETRIES
MAX_RETRIES==5;5;
/**
/**
** This
Thismethod
methoddoes
doesinvocation
invocationinterpositioning
interpositioningofoftxtxmanagement
management
*/*/
public
publicObject
Objectinvoke(Invocation
invoke(Invocationinvocation)
invocation)throws
throwsException
Exception{{
Transaction Handles
Handles the
the declarative
declarative
oldTransaction==invocation.getTransaction();
TransactionoldTransaction invocation.getTransaction(); transaction
transaction attributes
attributes from
from
for ejb-jar.xml
ejb-jar.xml (next
(next slides)
slides)
for(int
(inti i==0;0;i i<<MAX_RETRIES;
MAX_RETRIES;i++) i++){{
try
try {{
return
returnrunWithTransactions(invocation);
runWithTransactions(invocation);
}}
catch
catch(Exception
(Exceptionex)
ex){{
ApplicationDeadlockException
ApplicationDeadlockExceptiondeadlock deadlock==ApplicationDeadlockException.isADE(ex);
ApplicationDeadlockException.isADE(ex);
ifif(deadlock
(deadlock!=!=null)
null){{
ifif(!deadlock.retryable()
(!deadlock.retryable()||||oldTransaction
oldTransaction!=!=null
null||||i i++11>=
>=MAX_RETRIES)
MAX_RETRIES)throw
throw
deadlock;
deadlock; Application
Application deadlock
deadlock detection
detection
Thread.sleep(random.nextInt(1
Thread.sleep(random.nextInt(1++i),i),random.nextInt(1000));
random.nextInt(1000)); will
will attempt
attempt to
to re-execute
re-execute the
the
}}
invocation
invocation for
for aa possible
possible
else { throw
else { throw ex; }ex; }
resolution
resolution of
of resource
resource
allocation
allocation ordering
ordering problems.
problems.
TXInterceptorCMT (2/5)
Professional Open Source™
org.jboss.ejb.plugins.TXInterceptorCMT
org.jboss.ejb.plugins.TXInterceptorCMT
private
privateObject
ObjectrunWithTransactions(boolean
runWithTransactions(booleanremoteInvocation,
remoteInvocation,Invocation
Invocationmi)
mi)throws
throwsException
Exception
{{
////Old
Oldtransaction
transactionisisthe
thetransaction
transactionthat
thatcomes
comeswith
withthe
theMI
MI
Transaction
TransactionoldTransaction
oldTransaction==mi.getTransaction();
mi.getTransaction();
////New
Newtransaction
transactionisisthe
thenew
newtransaction
transactionthis
thismight
mightstart
start
Transaction
TransactionnewTransaction
newTransaction==null;
null;
InvocationType
InvocationTypetype
type==invocation.getType();
invocation.getType();
byte
bytetransType
transType==getTransactionMethod(invocation.getMethod(),
getTransactionMethod(invocation.getMethod(),type);
type);
////Thread
Threadarriving
arrivingmust
mustbebeclean
clean(jboss
(jbossdoesn't
doesn'tset
setthe
thethread
thread
////previously).
previously).However
Howeveroptimized
optimizedcalls
callscome
comewith
withassociated
associated
////thread
threadfor
forexample.
example.We Wesuspend
suspendthe thethread
threadassociation
associationhere,
here,and
and
////resume
resumeininthe
thefinally
finallyblock
blockofofthe
thefollowing
followingtry.
try.
Transaction
TransactionthreadTx
threadTx==tm.suspend();
tm.suspend();
Transtype
Transtypeisisthe
the
try declarative
try{{ declarative
switch transactional
transactionaltag
tag
switch(transType)
(transType)
{{
15
TXInterceptorCMT (3/5)
Professional Open Source™
org.jboss.ejb.plugins.TXInterceptorCMT
org.jboss.ejb.plugins.TXInterceptorCMT
case
caseMetaData.TX_NOT_SUPPORTED:
MetaData.TX_NOT_SUPPORTED:
////Do
Donot
notset
setaatransaction
transactionon
onthe
thethread
threadeven
evenififin
inMI,
MI,just
justrun
run
return
returninvokeNext(remoteInvocation,
invokeNext(remoteInvocation,mi,mi,false);
false);
case
caseMetaData.TX_REQUIRED:
MetaData.TX_REQUIRED:
ifif(oldTransaction
(oldTransaction==
==null)
null) {{ ////No
Notxtxrunning
running
tm.begin();
tm.begin(); ////Create
Createtxtx
newTransaction
newTransaction==tm.getTransaction();
tm.getTransaction(); ////Get
Getthe
thetxtx
mi.setTransaction(newTransaction);
mi.setTransaction(newTransaction); ////Let
Letthe
themethod
methodinvocation
invocationknow
know
}}
else
else{{ ////We
Wehave
haveaatxtxpropagated
propagated
tm.resume(oldTransaction);
tm.resume(oldTransaction); ////Associate
Associateititwith
withthe
thethread
thread
}}
try
try {{ ////Continue
Continueinvocation
invocation
return
returninvokeNext(remoteInvocation,
invokeNext(remoteInvocation,mi,
mi,newTransaction
newTransaction!= !=null);
null);
}}
finally
finally {{
ifif(newTransaction
(newTransaction!=!=null)
null) {{ ////Only
Onlydo
dosomething
somethingififwe
westarted
startedthe
thetransaction
transaction
endTransaction(invocation,
endTransaction(invocation,newTransaction,
newTransaction,oldTransaction);
oldTransaction);
}}
else{{tm.suspend();
else tm.suspend();}}
TXInterceptorCMT (4/5)
Professional Open Source™
org.jboss.ejb.plugins.TXInterceptorCMT
org.jboss.ejb.plugins.TXInterceptorCMT
case
caseMetaData.TX_SUPPORTS:
MetaData.TX_SUPPORTS:
{{
////Associate
Associateold
oldtransaction
transactionwith
withthe
thethread
thread
////Some
SomeTMs
TMscannot
cannotresume
resumeaanull
nulltransaction
transactionand andwill
willthrow
throw
////an
anexception
exception(e.g.
(e.g.Tyrex),
Tyrex),so
somake
makesure
sureititisisnot
notnull
null
ifif(oldTransaction
(oldTransaction!=!=null)
null)
tm.resume(oldTransaction);
tm.resume(oldTransaction);
try
try
{{
return
returninvokeNext(remoteInvocation,
invokeNext(remoteInvocation,mi,
mi,false);
false);
}}
finally
finally
{{
tm.suspend();
tm.suspend();
}}
////Even
Evenon
onerror
errorwe
wedon't
don'tdo
doanything
anythingwith
withthe
thetx,
tx,we
wedidn't
didn'tstart
startitit
}}
16
TXInterceptorCMT (5/5)
Professional Open Source™
org.jboss.ejb.plugins.TXInterceptorCMT
org.jboss.ejb.plugins.TXInterceptorCMT
case
caseMetaData.TX_REQUIRES_NEW:
MetaData.TX_REQUIRES_NEW:
{{
tm.begin();
tm.begin(); ////Always
Alwaysbegin
beginaatransaction
transaction
newTransaction
newTransaction==tm.getTransaction();
tm.getTransaction(); ////Get
Getitit
mi.setTransaction(newTransaction);
mi.setTransaction(newTransaction); ////Set
Setititon
onthe
themethod
methodinvocation
invocation
try
try {{ ////Continue
Continueinvocation
invocation
return
returninvokeNext(remoteInvocation,
invokeNext(remoteInvocation,mi, mi,true);
true);
}}
finally
finally {{
////We
Westarted
startedthe
thetransaction
transactionfor
forsure
sureso
sowe
wecommit
commitororroll
rollback
back
endTransaction(invocation,
endTransaction(invocation,newTransaction,
newTransaction,oldTransaction);
oldTransaction);
}}
…
…
}}
finally
finally
{{
////IN
INcase
casewe
wehad
hadaaTx Txassociated
associatedwith
withthe
thethread
threadreassociate
reassociate
ifif(threadTx
(threadTx!=!=null)
null)
tm.resume(threadTx);
tm.resume(threadTx);
}}
Lock Interceptor
Professional Open Source™
4 - Instance Locking
– Lock the method and handle transaction synchronization
• Pessimistic locking
STOP
STOP
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
Log
Call
Log
Call
Invocation
17
Locking
Professional Open Source™
BeanLockManager
Professional Open Source™
18
BeanLock Interface
Professional Open Source™
org.jboss.ejb.BeanLock
org.jboss.ejb.BeanLock
public
publicinterface
interfaceBeanLock
BeanLock
{{
public
publicObject
ObjectgetId();
getId();
public
publicvoid
voidsetId(Object
setId(Objectid);
id);
public
publicvoid
voidsetReentrant(boolean
setReentrant(booleanreentrant);
reentrant);
public
publicvoid
voidsetTimeout(int
setTimeout(inttimeout);
timeout);
public
publicvoid
voidsync();
sync();
public
publicvoid
voidreleaseSync();
releaseSync();
public
publicvoid
voidschedule(MethodInvocation
schedule(MethodInvocationmi) mi)throws
throwsException;
Exception;
public
publicvoid
voidsetTransaction(Transaction
setTransaction(Transactiontx);
tx);
public
publicTransaction
TransactiongetTransaction();
getTransaction();
public
publicvoid
voidendTransaction(Transaction
endTransaction(Transactiontx);tx);
public
publicvoid
voidwontSynchronize(Transaction
wontSynchronize(Transactiontx); tx);public
publicboolean
booleanisMethodLocked();
isMethodLocked();
public
publicint
intgetNumMethodLocks();
getNumMethodLocks();
public
publicvoid
voidaddMethodLock();
addMethodLock();
public
publicvoid
voidreleaseMethodLock();
releaseMethodLock();
public
publicvoid
voidaddRef();
addRef();
public
publicvoid
voidremoveRef();
removeRef();
public
publicint
intgetRefs();
getRefs();
}}
BeanLock Discussion
Professional Open Source™
setReentrant
– Was the entity bean the BeanLockManager is associated with marked as
reentrant
setTimeout
– A transaction synchronization timeout in milliseconds
19
BeanLock Discussion (Transactions)
Professional Open Source™
endTransaction(Transaction tx)
– Signifies the end of the indicated transaction to the lock
– Called by the javax.transaction.Synchronization.afterCompletion method
for example
wontSynchronize(Transaction tx)
– Signifies that the transaction is not going to complete successfully
– Called during exception recovery
20
BeanLock Discussion (Scheduling)
Professional Open Source™
org.jboss.ejb.plugins.EntityLockInterceptor
org.jboss.ejb.plugins.EntityLockInterceptor
public
publicObject
Objectinvoke(Invocation
invoke(Invocationmi)
mi)throws
throwsException
Exception{{
////The
Thekey.
key.
Object
Objectkey
key==(CacheKey)
(CacheKey)mi.getId();
mi.getId();
////The
Thelock.
lock.
BeanLock
BeanLocklocklock;;
{{
lock
lock==(BeanLock)container.getLockManager().getLock(key);
(BeanLock)container.getLockManager().getLock(key);
lock.schedule(mi);
lock.schedule(mi);
try
try{{return
returngetNext().invoke(mi);
getNext().invoke(mi);}}
finally
finally {{
////we
weare
aredone
donewith
withthe
themethod,
method,decrease
decreasethe
thecount,
count,ififititreaches
reaches00ititwill
willwake
wakeup
up the
thenext
nextthread
thread
lock.sync();
lock.sync();
lock.releaseMethodLock();
lock.releaseMethodLock();
lock.releaseSync();
lock.releaseSync();
}}
21
EntityInstanceInterceptor
Professional Open Source™
5 - Instance Acquisition
– Is the instance corresponding to the PK in cache?
– If so then retrieve it
– If not go to the pools get one and cache it
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
Log
Call
Log
Call
Invocation
org.jboss.ejb.plugins.EntityInstanceInterceptor
org.jboss.ejb.plugins.EntityInstanceInterceptor
public
publicObject
Objectinvoke(Invocation
invoke(Invocationmi)
mi)throws
throwsException
Exception{{
This
This “context”
“context” isis the
the
wrapper
wrapper to
to the
the real
real
////The
Thekey
key instance
instance in in cache
cache
CacheKey
CacheKeykeykey==(CacheKey)
(CacheKey)mi.getId();
mi.getId();
////The context
The context
EntityEnterpriseContext
EntityEnterpriseContextctx
ctx==(EntityEnterpriseContext)
(EntityEnterpriseContext)container.getInstanceCache().get(key);
container.getInstanceCache().get(key);
////Associate
Associatetransaction,
transaction,ininthe
thenew
newdesign
designthe
thelock
lockalready
alreadyhas
hasthe
thetransaction
transactionfrom
fromtheprevious
thepreviousinterceptor
interceptor
ctx.setTransaction(mi.getTransaction());
ctx.setTransaction(mi.getTransaction());
////Set
Setthe
thecurrent
currentsecurity
securityinformation
information
ctx.setPrincipal(SecurityAssociation.getPrincipal());
ctx.setPrincipal(SecurityAssociation.getPrincipal());
////Set
Setcontext
contexton
onthe
themethod
methodinvocation
invocation
mi.setEnterpriseContext(ctx);
mi.setEnterpriseContext(ctx);
boolean
booleanexceptionThrown
exceptionThrown==false;
false;
try
try{{
return
returngetNext().invoke(mi);
getNext().invoke(mi);
}}
22
Synchronization Interceptor
Professional Open Source™
6 - Instance Synchronization
– The container knows to refresh the state
– Uses transaction synchronization callback and commit option to
synch DB
– Ensures state is “valid” , instance in memory is reflection of DB
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
Log
Log
Call
Call
Invocation
org.jboss.ejb.plugins.EntitySynchronizationInterceptor
org.jboss.ejb.plugins.EntitySynchronizationInterceptor
public
publicObject
Objectinvoke(MethodInvocation
invoke(MethodInvocationmi) mi)throws
throwsException
Exception{{
////We
Weare
aregoing
goingtotowork
workwith
withthe
thecontext
contextaalot
lot
EntityEnterpriseContext
EntityEnterpriseContextctx
ctx==(EntityEnterpriseContext)mi.getEnterpriseContext();
(EntityEnterpriseContext)mi.getEnterpriseContext();
////The
TheTx
Txcoming
comingasaspart
partofofthe
theMethod
MethodInvocation
Invocation
Transaction
Transactiontxtx==mi.getTransaction();
mi.getTransaction();
////IsIsmy mystate
statevalid?
valid?
ifif(!ctx.isValid())
(!ctx.isValid()){{
////IfIfnot
nottell
tellthe
thepersistence
persistencemanager
managertotoload
loadthe
thestate
state
((EntityContainer)getContainer()).getPersistenceManager().loadEntity(ctx);
((EntityContainer)getContainer()).getPersistenceManager().loadEntity(ctx);
////Now
Nowthe
thestate
stateisisvalid
valid
ctx.setValid(true);
ctx.setValid(true);
}}
23
Container Interceptor
Professional Open Source™
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
Log
Call
Log
Call
Invocation
ContainerInterceptor
Professional Open Source™
24
ContainerInterceptor
Professional Open Source™
org.jboss.ejb.EntityContainer$ContainerInterceptor
org.jboss.ejb.EntityContainer$ContainerInterceptor
else
else{{
//wire
//wirethe
thetransaction
transactionon
onthe
thecontext,
context,this
thisisishow
howthe
theinstance
instanceremember
rememberthe
thetx
tx
ifif(mi.getEnterpriseContext().getTransaction()
(mi.getEnterpriseContext().getTransaction()====null)
null)
mi.getEnterpriseContext().setTransaction(mi.getTransaction());
mi.getEnterpriseContext().setTransaction(mi.getTransaction());
////Invoke
Invokeandandhandle
handleexceptions
exceptions
try
try
{{
return
returnm.invoke(mi.getEnterpriseContext().getInstance(),
m.invoke(mi.getEnterpriseContext().getInstance(),mi.getArguments());
mi.getArguments());
}}catch
catch(IllegalAccessException
(IllegalAccessExceptione) e){{
////Throw
Throwthis
thisas
asaabean
beanexception...(?)
exception...(?)
throw
thrownew
newEJBException(e);
EJBException(e); Call
Call is
is fielded
fielded
}}catch
catch(InvocationTargetException
(InvocationTargetExceptione) e){{ by
by the
the instance
instance
Throwable
Throwableex ex==e.getTargetException();
e.getTargetException();
…//end
…//end
After
After invoke()
invoke()
Or
Or in
in finally()
finally()
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
Log
Call
Log
Call
Invocation
25
Entity State-DB Synchronization
Professional Open Source™
org.jboss.ejb.plugins.EntitySynchronizationInterceptor
org.jboss.ejb.plugins.EntitySynchronizationInterceptor
private
privatevoid
voidregister(EntityEnterpriseContext
register(EntityEnterpriseContextctx,
ctx,Transaction
Transactiontx)
tx){{
////Create
Createaanew
newsynchronization
synchronization
InstanceSynchronization
InstanceSynchronizationsynch
synch==new
newInstanceSynchronization(tx,
InstanceSynchronization(tx,ctx);
ctx);
try
try{{ Implements
Implements
////We
Wewant
wanttotobebenotified
notifiedwhen
whenthe thetransaction
transactioncommits
commits javax.transaction.Synchronization
javax.transaction.Synchronization
tx.registerSynchronization(synch); interface
interface
tx.registerSynchronization(synch);
}}catch
catch(RollbackException
(RollbackExceptione)e){{
////The
Thestate
stateininthe
theinstance
instanceisistotobe
bediscarded,
discarded,we
weforce
forceaareload
reloadofofstate
state
ctx.setValid(false);
ctx.setValid(false);
}}catch
catch(Exception
(Exceptione)e){{
throw
thrownew
newEJBException(e);
EJBException(e);
}}
}}
Acquisition interceptor
– Doesn’t do anything if Tx
– In case of stateless call frees the instance
– In case of Exception discards the instance
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
Log
Call
Log
Call
Invocation
26
Lock Interceptor Exit
Professional Open Source™
Lock Interceptor
– Cleans up any locks
Only
Only ifif part
part of
of the
the
same
same transaction
transaction
GO!
GO!
Synchronization
Transaction
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
Log
Call
Log
Call
Invocation
Synchronization
Connection
Transaction
Connection
Security
Security
Cache
Cache
Lock
Lock
Log
Call
Log
Call
Invocation
27
Entity State-DB Synchronization
Professional Open Source™
org.jboss.ejb.plugins.EntitySynchronizationInterceptor$InstanceSynchronization
org.jboss.ejb.plugins.EntitySynchronizationInterceptor$InstanceSynchronization
public
publicvoid voidafterCompletion(int
afterCompletion(intstatus)
status){{
....////skip
skip Transaction
Transaction
switch
switch(commitOption)
(commitOption) completed
completed
////Keep
Keepinstance
instancecached
cachedafter
aftertxtxcommit
commit
case
caseConfigurationMetaData.A_COMMIT_OPTION:
ConfigurationMetaData.A_COMMIT_OPTION:
////The
Thestate
stateisisstill
stillvalid
valid(only
(onlypoint
pointofofaccess
accessisisus)
us)
ctx.setValid(true);
ctx.setValid(true);
break;
break;
////Keep
Keepinstance
instanceactive,
active,but
butinvalidate
invalidatestate
state
case
caseConfigurationMetaData.B_COMMIT_OPTION:
ConfigurationMetaData.B_COMMIT_OPTION:
////Invalidate
Invalidatestate
state(there
(theremight
mightbebeother
otherpoints
pointsofofentry)
entry)
ctx.setValid(false);
ctx.setValid(false);
break;
break;
…
…////continue
continue
org.jboss.ejb.plugins.EntitySynchronizationInterceptor$InstanceSynchronization
org.jboss.ejb.plugins.EntitySynchronizationInterceptor$InstanceSynchronization
////Invalidate
Invalidateeverything
everythingAND ANDPassivate
Passivateinstance
instance
case
caseConfigurationMetaData.C_COMMIT_OPTION:
ConfigurationMetaData.C_COMMIT_OPTION:
try
try
{{
////Do
Donot
notcall
callrelease
releaseififgetId()
getId()isisnull.
null. This
Thismeans
meansthat
that
////the
theentity
entityhas
hasbeen
beenremoved
removedfrom fromcache.
cache.
////release
releasewill
willschedule
scheduleaapassivation
passivationand andthis
thisremoved
removedctx
ctx
////could
couldbe
beput
putback
backinto
intothe
thecache!
cache!
ifif(ctx.getId()
(ctx.getId()!=!=null)
null)container.getInstanceCache().release(ctx);
container.getInstanceCache().release(ctx);
}}
28
Conclusion
Professional Open Source™
29