Buscar
Social
Ofertas laborales ES

Foro sobre Java EE > ¿Cómo hacer Transacciones Distribuidas XA en Spring y GlassFish 5?

Hola.

Estoy tratando de hacer una transacción distribuida entre dos servicios web REST, cuya fuente de datos apuntan a la misma base de datos. El primer servicio se denomina 1, que llama con RestTemplate al servicio web denominado 2.

Para el uso de las transacciones distribuidas voy a utilizar un pool de conexiones con JNDI, MySql (con el controlador de conexión 5.1.35), JTA, XA, Spring y el servidor de aplicaciones GlassFish 5.

Ahora, ya he descargado las dependencias de maven en el proyecto de spring, monté el JtaTransactionManager en una clase de configuración y escribí las propiedades de la fuente de datos y el estado de JTA en el archivo application.yml, como en el código siguiente, respectivamente en los dos servicios web ' y 2'):

Clase de configuración:

@Configuration
@EnableTransactionManagement
public class Transacciones {

@Bean
public PlatformTransactionManager platformTransactionManager(){
return new JtaTransactionManager();
}

}


archivo application.yml:


spring:
datasource:
jndi-name: jdbc/Prueba
driver-class-name: com.mysql.jdbc.Driver

jta:
enabled: true

También he instalado el JNDI en GlassFish 5, que ha sido creado como un "Recurso JDBC" llamado jdbc / Prueba en un "Pool de Conexiones" de tipo javax.sql.XADataSource y llamado pruebaXA:

https://i.stack.imgur.com/JU2ls.png

En la capa de control del servicio web 1, llama al servicio 2 con la clase RestTemplate de Spring Framework:

servicio 1


@RestController
@RequestMapping("/servicio")
@EnableTransactionManagement
public class a {

@Autowired
private JdbcTemplate objJdbcTemplate;


@Transactional(rollbackFor = RuntimeException.class)
@GetMapping("/1")
public Integer getValor(){
try{
int numero;
int n=50;
RestTemplate restTemplate = new RestTemplate();

Integer intRes1;
Integer intRes2;
numero = (int) (Math.random() * n) + 1;

intRes2 = restTemplate.postForObject("http://localhost:8080/servicio2-1.0-SNAPSHOT/servicio/2",numero,Integer.class);

intRes1=objJdbcTemplate.update("INSERT INTO A VALUES(" +numero + ")");

return numero;
}catch(Exception e){
throw new RuntimeException(e);
}
}
}

servicio 2


@RestController
@RequestMapping("/servicio")
public class a {

@Autowired
private JdbcTemplate objJdbcTemplate;

@Transactional(rollbackFor = RuntimeException.class)
@PostMapping("/2")
public Integer getValor(@RequestBody Integer intNum){
try{
Integer intRes;

intRes=objJdbcTemplate.update("INSERT INTO B VALUES(" + intNum + ")");
return intRes;
}catch(Exception e){
throw new RuntimeException(e);
}
}
}

Si los dos servicios funcionan bien entonces no hay problema, sin embargo, cuando el servicio 1 cae, el servicio 2 no sabe sobre el error y no hace la reversión.

No sé si necesito instalar otra característica en GlassFish 5, o en el programa de Spring.

He leído que en primavera solo es necesario crear el JtaTransactionManager y Spring hará el trabajo relacionado con JTA. https://spring.io/blog/2011/08/15/configuring-spring-and-jta-without-full-java-ee/

Gracias por su ayuda y tiempo.

septiembre 6, 2017 | Registered Commentercyberserver