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(); }
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();
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/
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.