Blog do Urubatan
msgbartop
Desenvolvedor, Arquiteto, Palestrante, Coordenador do RSJUG, Patinador e Blogger
msgbarbottom

03 Nov 04 Commons-Attributes - Facilitando a configuração do Spring MVC

bom, uma das maiores criticas ao spring framework, é a quantidade excessiva de XML utilizados, bom, as ultimas versɵes do framework, suportam annotations para diversos tipos de configuração, o que é mais propagandeado é a parte de configuração de transações por annotations, mas a parte que eu mais gostei é a que substitui totalmente a configuração e mapeamento de controllers para a parte web, isto quer dizer que nÉ£o é necessária nem uma linha de configuração para adicionar um novo controller na aplicação.
Por enquanto, o Spring nÉ£o suporta as anotações do JDK 1.5, utiliza apenas o commons-annotations, o que requer um passo extra na compilação da aplicação.
bom, mas chega de papo furado, parece que é fácil demais né? bom, vamos a um pequeno exemplo:

/**
* @author Rodrigo Urubatan Ferreira Jardim
* @@org.springframework.web.servlet.handler.metadata.PathMap("/home.html")
*/

public class HomeController extends AbstractController {
private WorkFlowDao workFlowDao;

public void setWorkFlowDao(WorkFlowDao workFlowDao) {
this.workFlowDao = workFlowDao;
}

protected ModelAndView handleRequestInternal ( HttpServletRequest request, HttpServletResponse response ) throws Exception {
Collection processos = workFlowDao.listaProcessos();
return new ModelAndView("home","processos",processos);
}

}

bom, este controller extremamente complexo, precisa apenas ser compilado, e indexado pelo compilador do commons-attributes que vai atender pela URL "home.html" (sim, eu costumo utilizar a extensÉ£o HTML para as minhas páginas dinÉ¢micas também)
o que determina isto, é apenas aquele comentário em negrito na declaração da classe.

vamos ver como é feita a mágica, é necessária uma pequena alteração no build.xml, e a definição de alguns beans em um XML utilizado pelo spring (eu costumo utilizar applicationContext.xml, ou entÉ£o o proprio <servletname>-servlet.xml, que sera lido automáticamente pelo servlet do spring
vamos ao build.xml:

<target name="init">
<taskdef classpathref="project.class.path" resource="org/apache/commons/attributes/anttasks.properties" />
</target>

<target name="compile" depends="attrib">
<javac classpathref="project.class.path" destdir="${web.bin}" srcdir="${src.dir}" />
<javac classpathref="project.class.path" destdir="${web.bin}" srcdir="${src.temp}" />
</target>

<target name="attrib" depends="init">
<attribute-compiler destdir="${src.temp}">
<fileset dir="${src.dir}" includes="**/*.java" />
</attribute-compiler>
</target>

<target name="all" depends="compile,attrib">
<jar destfile="${web.lib}/${jar.name}" basedir="${web.bin}" compress="true" index="true">
<include name="**/*.*" />
</jar>
<attribute-indexer jarFile="${web.lib}/${jar.name}">
<classpath refid="project.class.path" />
</attribute-indexer>
</target>

o pulo do gato neste build.xml é a task: attribute-indexer que permite que o spring encontre os controller automáticamente
e as configurações necessárias no spring:

<bean id="autoproxy"
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" singleton="true">
<property name="customTargetSourceCreators">
<list>
<ref local="poolingTargetSourceCreator" />
</list>
</property>
</bean>
<bean id="transactionAttributeSource"
class="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource"
autowire="constructor" singleton="true">
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor"
autowire="byType" singleton="true">
</bean>
<bean id="transactionAdvisor"
class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor"
autowire="constructor" singleton="true">
</bean>
<bean id="attributes"
class="org.springframework.metadata.commons.CommonsAttributes" singleton="true"/>
<bean id="poolingTargetSourceCreator"
class="org.springframework.aop.framework.autoproxy.metadata.AttributesPoolingTargetSourceCreator"
autowire="constructor" singleton="true">
</bean>
<bean id="commonsAttributesHandlerMapping" class="org.springframework.web.servlet.handler.metadata.CommonsPathMapHandlerMapping" singleton="true"/>

aqui, todos estes beans colaboram de alguma forma, o default-autowire do contexto esta setado para: byName, isto quer dizer que se algum dos nomes for alterado, a cosia pode parar de funcionar, mas deixando assim ta tudo beleza
quem carrega os controller aqui, é o ultimo bean definido: commonsAttributesHandlerMapping

bom, o negócio parece show de bola, mas tem um probleminha na versÉ£o atual do spring (1.1), os controllers sÉ£o carregados sempre utilizando auto wire by bype, isto quer dizer que só pode existir um bean de cada tipo no contexto, mas eu fiz uma pequena alteração e mandei para o pessoal do spring, e o Rod Johnson respondeu dizendo que iria incluir a alteração para a versÉ£o 1.1.3 corrigindo este problema. Atualmente to utilizando a minha versÉ£o alterada com autoWireByName, acho bem mais flexivel :D
bom, eu achei super legal este suporte para anotações, acho que vcs podem aproveitar também, qualquer duvida postem aqui nos comentários.

Se você gostou deste post, lembre-se de assinar o RSS feed do blog, para ser notificado de novos posts!

Tags: , ,

Leave a Comment