List springframework classpath

in applicationContext-XX.xml

<bean id="pathMatchingResourcePatternResolver" class="org.springframework.core.io.support.PathMatchingResourcePatternResolver" />

in your class:


	@Autowired
	@Qualifier("pathMatchingResourcePatternResolver")
	private PathMatchingResourcePatternResolver path;

	public void method(...) throws Exception {

		URLClassLoader loader = (URLClassLoader) path.getClassLoader();
		for(URL url: loader.getURLs()){
			System.out.println(url.toString());
		}
		// ...

List springframework classpath

Bootstrap listener for custom Log4J initialization in a web environment

Para aplicaciones web, Spring tiene un configurardor de log. Este se configura en el fichero web.xml. En el cual le dices:

  1. que fichero tiene la configuracion de log4j.
  2. Y cual es la clase de Spring que levanta la configuracion.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:web="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
	version="2.4">
	<!-- ... -->
	<context-param>
		<param-name>log4jConfigLocation</param-name>
		<param-value>classpath:log4j_pepito.xml</param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.web.util.Log4jConfigListener
		</listener-class>
	</listener>
	<!-- ... -->
</web-app>
Bootstrap listener for custom Log4J initialization in a web environment

Graba en bbdd la entrada y salida en el log del Web Service con Apache CXF

En referencia al articulo anterior: Mostrar la entrada y salida en el log del Web Service con Apache CXF.

Ahora lo que quiero es grabarlo en la bbdd.

Apache CXF en su modulo cxf-rt-management tiene un paquete denominado: org.apache.cxf.management.persistence. Vamos utilizar esto, que ya esta casi hecho para grabar en nuestra bbdd.

En el paquete vemos las siguientes clases:
ExchangeData: es un bean que contiene toda la informacion sobre la peticion y la respuesta. ¡Ya podian haber implementado un toString para cuando debugeas!.
ExchangeDataDAO: la interfaz que se llama para persistir.
ExchangeDataFilter: la interfaz que se llama para saber si se puede persistir. Es un filtro.
ExchangeDataProperty: el bean para las propiedades de los mensajes de entrada-salida. Esta clase se utiliza en el bean ExchangeData.
FilesystemExchangeDataDAO: implementación de la interfaz del DAO que graba en un fichero. Si no se le indica la ruta, lo hace en una carpeta temporal. En mi caso, en la carpeta /temp de $CATALINA_HOME.
StatusExchangeDataFilter: implementación de la interfaz del filtro. Esta implementación es solo para errores.

¿Como se usa?

A) usando las clases que hemos visto.

Es decir, vamos a grabar a fichero en la carpeta /temp de $CATALINA_HOME, solo los mensajes que den error (excepciones) en nuestro Web Service.
En nuestro fichero de configuración de CXF (un aplicattionContext.xml de spring), ponemos lo siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core"
	xsi:schemaLocation="
	http://cxf.apache.org/core 
	http://cxf.apache.org/schemas/core.xsd
	http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://cxf.apache.org/jaxws 
	http://cxf.apache.org/schemas/jaxws.xsd">

	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
 
	<cxf:bus>
		<cxf:inInterceptors> <!-- logueamos entrada-salida y la persistimos -->
			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
			<ref bean="persistInInterceptor" />
		</cxf:inInterceptors>

		<cxf:inFaultInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
			<ref bean="persistInInterceptor" />
		</cxf:inFaultInterceptors>

		<cxf:outInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
			<ref bean="persistOutInterceptor" />
		</cxf:outInterceptors>

		<cxf:outFaultInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
			<ref bean="persistOutInterceptor" />
		</cxf:outFaultInterceptors>
	</cxf:bus>

	<jaxws:endpoint id="busquedaService" implementor="#busqueda" address="/busqueda" />

	<bean id="exchangeDAOImpl" class="org.apache.cxf.management.persistence.FilesystemExchangeDataDAO" />

	<bean id="statusExchangeDataFilter" class="org.apache.cxf.management.persistence.StatusExchangeDataFilter" >
		<property name="statusFilter" value="ERROR" /> <!-- Registramos solo los errores, opcion por defecto que no hace falta poner -->
		<!-- <property name="statusFilter" value="OK" /> --> <!-- Tb podemos registrar los aciertos -->
	</bean>
	
	<bean id="persistInInterceptor" class="org.apache.cxf.management.interceptor.PersistInInterceptor" />
	<bean id="persistOutInterceptor" class="org.apache.cxf.management.interceptor.PersistOutInterceptor">
		<property name="exchangeDataDAO" ref="exchangeDAOImpl" />
		<property name="exchangeDataFilter" ref="statusExchangeDataFilter" />
	</bean>
	
</beans>

b) Personalizando el dao y el filtro.

Exactamente lo anterior pero Con nuestra propia implementación de las interfaces.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core"
	xsi:schemaLocation="
	http://cxf.apache.org/core 
	http://cxf.apache.org/schemas/core.xsd
	http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://cxf.apache.org/jaxws 
	http://cxf.apache.org/schemas/jaxws.xsd">

	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
 
	<cxf:bus>
		<cxf:inInterceptors> <!-- logueamos entrada-salida y la persistimos -->
			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
			<ref bean="persistInInterceptor" />
		</cxf:inInterceptors>

		<cxf:inFaultInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
			<ref bean="persistInInterceptor" />
		</cxf:inFaultInterceptors>

		<cxf:outInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
			<ref bean="persistOutInterceptor" />
		</cxf:outInterceptors>

		<cxf:outFaultInterceptors>
			<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
			<ref bean="persistOutInterceptor" />
		</cxf:outFaultInterceptors>
	</cxf:bus>

	<jaxws:endpoint id="busquedaService" implementor="#busqueda" address="/busqueda" />

	<bean id="exchangeDAOImpl" class="mi.paquete.cxf.interceptor.persistence.PersistExchangeDataDAO" />

	<bean id="exchangeDataFilter" class="mi.paquete.cxf.interceptor.persistence.NoFiltroNada" />
	
	<bean id="persistInInterceptor" class="org.apache.cxf.management.interceptor.PersistInInterceptor" />
	<bean id="persistOutInterceptor" class="org.apache.cxf.management.interceptor.PersistOutInterceptor">
		<property name="exchangeDataDAO" ref="exchangeDAOImpl" />
		<property name="exchangeDataFilter" ref="exchangeDataFilter" />
	</bean>
	
</beans>

El filtro, el cual queremos que no filtre nada, que persista siempre:

package mi.paquete.cxf.interceptor.persistence;

import org.apache.cxf.management.persistence.ExchangeData;
import org.apache.cxf.management.persistence.ExchangeDataFilter;

public class NoFiltroNada  implements ExchangeDataFilter {

	public boolean shouldPersist(ExchangeData data) {
		if(data == null){
			return false;
		}else{
			return true;
		}
	}

}

Nuestra implementación de como vamos a graba en la base de datos:

package mi.paquete.cxf.interceptor.persistence;

import org.apache.cxf.management.persistence.ExchangeData;
import org.apache.cxf.management.persistence.ExchangeDataDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import mi.paquete.cxf.interceptor.persistence.AuditoriaWsDao ;

public class ExchangeDataDaoImpl implements ExchangeDataDAO{

	@Autowired
	@Qualifier("auditoriaWsDao")
	private AuditoriaWsDao auditDao;
	
	public void save(ExchangeData exchangeData) throws Exception {
		if(exchangeData == null) return;
		
		/* 
		* GUARDAR:
		* (
		*             --descripcion del servicio--
		*   NombreDelServicio, NombreDeLaOperacionLLamada,
		*             --descripcion de la peticion--
		*   fechaPeticion, xmlPeticion, tipoDePeticion, pilaError,
		*             --descripcion de la respuesta--
		*   fechaRespuesta, xmlRespuesta, tipoDeRespuesta, pilaError,
		*  )
		*/
		auditDao.save(exchangeData.getUri(), exchangeData.getOperation(), 
			exchangeData.getInDate(), exchangeData.getRequest(), AuditDao.REQUEST, null,
			exchangeData.getOutDate(), exchangeData.getResponse(), AuditDao.RESPONSE, exchangeData.getStackTrace());
	}

}

la implementación del DAO, de la configurarión de la bbdd, de Hibernate, de Spring Transacctional, etc. no corresponden a este articulo.

Graba en bbdd la entrada y salida en el log del Web Service con Apache CXF

Mostrar la entrada y salida en el log del Web Service con Apache CXF

Tambien te puede interesar: Graba en bbdd la entrada y salida en el log del Web Service con Apache CXF.

Muchas veces te gustaria (deberias) saber cuales son los mensajes de entrada y salida del web service. Tan facil como configurar unos interceptors que vienen en CXF por defecto. En el fichero de configuracion de cxf, que es un applicationContext.xml de Spring.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core"
	xsi:schemaLocation="
	http://cxf.apache.org/core 
	http://cxf.apache.org/schemas/core.xsd
	http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://cxf.apache.org/jaxws 
	http://cxf.apache.org/schemas/jaxws.xsd">

	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
	
	<context:annotation-config />
	<context:component-scan base-package="es.depontevedra.ws.cxf.cividas.search" />

	<cxf:bus>
	        <cxf:inInterceptors>
	            <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
	        </cxf:inInterceptors>
	        
	  	<cxf:inFaultInterceptors>
	            <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
	        </cxf:inFaultInterceptors>
	        
	        <cxf:outInterceptors>            
	            <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
	        </cxf:outInterceptors>
	        
	  	<cxf:outFaultInterceptors>           
	             <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
	        </cxf:outFaultInterceptors>
	    </cxf:bus>

	<bean id="busqueda" class="mi.paquete.spi.BusquedaImpl" />
	<jaxws:endpoint id="busquedaService" implementor="#busqueda" address="/busqueda" />
	
</beans>

¿Por que cuatro?. Dos de la entrada-salida normal y dos de la entrada-salida de error. Aunque me pica en la nariz que el cxf:inFaultInterceptors para el log no es necesario. Todavia no he conseguido hacerlo fallar… se me estan ocurriendo nuevos test malignos… Nop, no hay manera no consigo que el mensaje de entrada consiga ir por aqui cxf:inFaultInterceptors.

Mostrar la entrada y salida en el log del Web Service con Apache CXF

@Transactional

¿Porque escribir un post sobre esta anotación?, porque me ha tenido 16h bloqueado. En un principio parece que hay que usarla a nivel de clase.Posteriormente, leyendo en stackoverflow, te dicen que a nivel de método. Oki. Tampoco va. Porque tiene que ser a nivel de clase y de método. Olé.¿Porqué?
Ejemplo en el manual de Spring. ¿Alguien ve anotaciones a nivel de método?

// the service class that we want to make transactional

@Transactional
public class DefaultFooService implements FooService {

 Foo getFoo(String fooName);
 Foo getFoo(String fooName, String barName);
 void insertFoo(Foo foo);
 void updateFoo(Foo foo);

}

Su applicationContext.xml


<!-- from the file 'context.xml' -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

<!-- this is the service object that we want to make transactional -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>

<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>

<!-- a PlatformTransactionManager is still required -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- (this dependency is defined somewhere else) -->
<property name="dataSource" ref="dataSource"/>
</bean>

<!-- other <bean/> definitions here -->

</beans>

Del manual de Spring:

Si  <bean id=”txManager”> se llamase transactionManager, entonces no haría falta ponerlo en: <tx:annotation-driven transaction-manager=”txManager”/>. Se quedaria: <tx:annotation-driven />.

“You can place the @Transactional annotation before an interface definition, a method on an interface, a class definition, or a public method on a class. However, the mere presence of the @Transactional annotation is not enough to activate the transactional behavior.” Es decir se puede poner conjuntamente, pero no aclara que debe ser asi.

“Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the @Transactional annotation, as opposed to annotating interfaces.” Si no es una interfaz… si es una clase… la anotación va en la clase y en el método… puff.

¿Porque no usarlo en interfaces?. Porque si utilizas <tx:annotation-driven mode=”aspectj”/> ó <tx:annotation-driven proxy-target-class=”true”/>. Spring no va a poder hacer su magia.

Cuidadin con poner @Transactional y @Service juntas…

“The most derived location takes precedence when evaluating the transactional settings for a method”. Es decir si tienes la anotacion a nivel de clase y de metodo, prevalece la del metodo. La configuracion que introduzcas en el metodo tienen prioridad sobre la configuracion de la anotacion en la clase. Ej: si en la clase, la transaccion es de solo lectura, y en el metodo de escritura, ese metodo podra escribir.

@Transactional(readOnly = true)
public class DefaultFooService implements FooService {

  public Foo getFoo(String fooName) {
    // do something
  }

  // these settings have precedence for this method
  @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
  public void updateFoo(Foo foo) {
    // do something
  }
}

Cuando usas proxy, la anotación solo es viable en métodos públicos. No se lanzara ningún error, pero el proxy no los podrá ver. Si por alguna razón, necesitas métodos de otro tipo, protected ó private, utiliza mejor aspectos.

Bien, esto ya ha terminado, ¿donde pone que es obligatorio que el método y la clase deban tener la anotacion @Transaction?. Si no lo haces así, no funciona.

@Transactional

Capturar MaxUploadSizeExceededException en Spring Portlet MVC

En el applicationContext.xml

	<bean id="portletMultipartResolver"
		class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver">
		<property name="maxUploadSize" value="1000000" />
	</bean>
	
	<bean class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver"/>

en el controlado:

	@ExceptionHandler(MaxUploadSizeExceededException.class)
	public ModelAndView handleException1(RenderRequest req, RenderResponse res, Object handler, Exception exception)
	{
		ModelAndView modelAndView = new ModelAndView("uploadFile");
		modelAndView.addObject("message", exception.getMessage());
		return modelAndView;
	}
Capturar MaxUploadSizeExceededException en Spring Portlet MVC

Spring MVC Portlet JSR-303 (Validation)

En el applicationContext de spring:
	<!-- Portlet annotations support -->
	<bean id="parameterMappingInterceptor"
		class="org.springframework.web.portlet.handler.ParameterMappingInterceptor" />

	<bean
		class="org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping">
		<property name="interceptors">
			<list>
				<ref bean="parameterMappingInterceptor" />
			</list>
		</property>
	</bean>

	<!-- mvc:annotation-driven @Valid JSR-303 -->
	<mvc:annotation-driven validator="validator" />
	<bean id="validator"
		class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
	<bean id="annotationMethodHandlerAdapter"
		class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter">
		<property name="webBindingInitializer">
			<bean id="configurableWebBindingInitializer"
				class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
				<property name="validator">
					<ref bean="validator" />
				</property>
			</bean>
		</property>
	</bean>

	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>classpath:Language</value>
				<value>classpath:ValidationMessages</value>
			</list>
		</property>
		<property name="defaultEncoding" value="UTF-8" />
	</bean>

En el pom.xml:

		<!-- Validation -->
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.0.0.GA</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>4.3.0.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator-annotation-processor</artifactId>
			<version>4.3.0.Final</version>
		</dependency>

Hibernate Validator anotaciones ejemplo

Spring MVC Portlet JSR-303 (Validation)

Fundamentos de Programacion de SpringFramework

1.- Referencia en el tiempo

14/01/2002 (Martin Fowler) Inversion of Control Containers and the Dependency Injection pattern http://martinfowler.com/articles/injection.html

Se inventa el patrón ‘Inyección de Dependencias’ y la describe como una parte del ‘Patrón de Diseño’: ‘Inversión de Control’.

Octubre 2002 (Rod Johnson) “Expert One-on-One J2EE Design and Development“.

Especifica en el libro una nueva manera de programar en J2EE. El código de ejemplo sirve como base para SpringFramework.

Junio 2003 SpringFramework bajo licencia Apache 2,0. 2

2.- Patrones de Diseño

3.- IoC & DI

4.- AOP

5.- Contenedores

6.- Framework

7- Componente vs Servicio

8.- Componente vs Aspecto

Fundamentos de Programacion de SpringFramework