Import scripts architecture, pt. II


First post of this series ended with code snippet, which invokates importAction itself. It’s not still the importing itself, but we are almost there. This post will be about what happenes, what hapened before and what is going to happen :-). But first things first, let’s have a look on Factory and Proxy pattern, which are used while calling imports.

Factory pattern is based on idea instead of creating a new object with new operator, factory is asked, which returns a new instance. This is way standard Spring’s bean factory works. It may looks like following diagram (image is from oodesign.com):

Factory Pattern
Factory Pattern (click for source – oodesign.com)

To hide newly created instance behind an interface facade Proxy pattern is used. This functionality is imho basic of AOP programming, because instead of calling original object, something else may be called. Have a look on following diagram (again from oodesign.com):

Proxy Pattern
Proxy Pattern (click for source – oodesign.com)

Now it’s possible to put those patterns together and get real importAction functionality: importAction is just an interface, which hides importActionImpl newly created for every request. This can be seen on following snippet of application context configuration.

[code lang=“xml“]
<bean id=“ImportAction“ class=“org.springframework.aop.framework.ProxyFactoryBean“>
<property name=“targetName“ value=“importAction“/>
<property name=“singleton“ value=“false“/>
<property name=“proxyInterfaces“>
<list>
<value>cz.shmoula.imports.ImportAction</value>
</list>
</property>
</bean>

<bean id=“importAction“ class=“cz.shmoula.imports.ImportActionImpl“ scope=“prototype“ />
[/code]

As I wrote a while before – all of this is done due to posibility of calling something else. But back to implementation, for details refer to some AOP documentation. Method importAction.invocateImportScript() is a pointcut, on which two advisors are bound. Have a look at following diagram.

ImportActionAdvice
ImportActionAdvice

This configuration can be achieved by NameMatchMethodPointcutAdvisor, see following snippet for ImportContentAdvisor bean definition and updated ImportAction itself:

[code lang=“xml“]
<bean id=“importContentAdvice“ class=“cz.shmoula.imports.ImportContentAdvice“ />

<bean id=“ImportContentAdvisor“ class=“org.springframework.aop.support.NameMatchMethodPointcutAdvisor“>
<property name=“advice“ ref=“importContentAdvice“/>
<property name=“mappedNames“>
<list>
<value>invocateImportScript</value>
</list>
</property>
</bean>

<bean id=“ImportAction“ class=“org.springframework.aop.framework.ProxyFactoryBean“>
<property name=“targetName“ value=“importAction“/>
<property name=“singleton“ value=“false“/>
<property name=“proxyInterfaces“>
<list>
<value>cz.shmoula.imports.ImportAction</value>
</list>
</property>
<property name=“interceptorNames“>
<list>
<value>ImportContentAdvisor</value>
<value>DeployContentAdvisor</value>
</list>
</property>
</bean>

<bean id=“importActionTask“ class=“cz.shmoula.imports.ImportActionTask“ scope=“prototype“>
<property name=“importAction“ ref=“ImportAction“/>
</bean>
[/code]

Last few lines is definition of importActionTask I wrote in previous post. In this class importAction.invocateImportScript() method is called. This method has one parameter – map of properties of config file (in format <QName, Serializable>) to read them once and have them all the time and not need to call nodeService.getProperties() again and again – in advisors or importAction class. When this method is called, proxy of importAction catches this calling and calls invoke() method on ImportContentAdvice and DeployContentAdvice. Let’s have a look on invoke() method in ImportContentAdvice:

[code lang=“java“]
public Object invoke(MethodInvocation invocation) throws Throwable {
Object[] objects = invocation.getArguments();
Object result = null;
Map<QName, Serializable> propertiesMap = __resolve_arguments_to_map_(objects);

String lockToken = (String) propertiesMap.get(ContentModel.PROP_NODE_UUID);
setTokenOnTarget(invocation, lockToken);

try {
AuthenticationUtil.setRunAsUser(AuthenticationUtil.getSystemUserName());
misLockingService.createLock(lockToken);

object = invocation.proceed();

misLockingService.releaseLock(lockToken);
} finally {
AuthenticationUtil.clearCurrentSecurityContext();
}

return result;
}
[/code]

All what ImportActionAdvice does can be seen on previous snippet. It locks used config file to prevent access from another thread, using node uuid as a locking token. Then it authenticates a system user (mainImportThread runs outside any security context) and invocates next chain (DeployContentAdvisor and after then invocateImportScript(), if everything goes ok). After return from invocation lock is released and security context is cleared. If anything happens inside, lock release is skipped, so some rescue mechanisms are automaticaly initiated after some time. Simple, yet effective, i hope.


Jeden komentář: “Import scripts architecture, pt. II”

  1. […] testy, že už si připadám Spring intermediate a výš, že si radši model vytvořím sám a bez aspektů, že i ty query si napíšu radši ručně a lépe… Zase na druhou stranu – podíval jsem […]

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *