|
21 | 21 | import java.net.InetAddress;
|
22 | 22 | import java.net.UnknownHostException;
|
23 | 23 | import java.nio.file.Path;
|
| 24 | +import java.util.Arrays; |
| 25 | +import java.util.List; |
| 26 | +import java.util.Properties; |
24 | 27 |
|
25 | 28 | import javax.jms.ConnectionFactory;
|
26 | 29 | import javax.jms.TemporaryQueue;
|
27 | 30 | import javax.jms.XAConnection;
|
28 | 31 | import javax.jms.XAConnectionFactory;
|
29 | 32 | import javax.jms.XASession;
|
| 33 | +import javax.naming.Context; |
| 34 | +import javax.naming.InitialContext; |
| 35 | +import javax.naming.NamingException; |
30 | 36 | import javax.sql.DataSource;
|
31 | 37 | import javax.sql.XADataSource;
|
32 | 38 | import javax.transaction.TransactionManager;
|
|
38 | 44 | import com.atomikos.jms.AtomikosConnectionFactoryBean;
|
39 | 45 | import org.junit.jupiter.api.AfterEach;
|
40 | 46 | import org.junit.jupiter.api.Test;
|
| 47 | +import org.junit.jupiter.api.extension.AfterEachCallback; |
| 48 | +import org.junit.jupiter.api.extension.BeforeEachCallback; |
| 49 | +import org.junit.jupiter.api.extension.ExtendWith; |
| 50 | +import org.junit.jupiter.api.extension.ExtensionContext; |
| 51 | +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; |
| 52 | +import org.junit.jupiter.api.extension.ParameterContext; |
| 53 | +import org.junit.jupiter.api.extension.ParameterResolutionException; |
| 54 | +import org.junit.jupiter.api.extension.ParameterResolver; |
41 | 55 | import org.junit.jupiter.api.io.TempDir;
|
| 56 | +import org.junit.jupiter.params.ParameterizedTest; |
| 57 | +import org.junit.jupiter.params.provider.Arguments; |
| 58 | +import org.junit.jupiter.params.provider.MethodSource; |
| 59 | +import org.osjava.sj.loader.JndiLoader; |
42 | 60 |
|
43 | 61 | import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
44 | 62 | import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
|
|
53 | 71 | import org.springframework.context.annotation.Bean;
|
54 | 72 | import org.springframework.context.annotation.Configuration;
|
55 | 73 | import org.springframework.transaction.jta.JtaTransactionManager;
|
| 74 | +import org.springframework.transaction.jta.UserTransactionAdapter; |
56 | 75 |
|
57 | 76 | import static org.assertj.core.api.Assertions.assertThat;
|
58 | 77 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
@@ -80,6 +99,31 @@ void closeContext() {
|
80 | 99 | if (this.context != null) {
|
81 | 100 | this.context.close();
|
82 | 101 | }
|
| 102 | + |
| 103 | + } |
| 104 | + |
| 105 | + @ParameterizedTest |
| 106 | + @ExtendWith(JndiExtension.class) |
| 107 | + @MethodSource("transactionManagerJndiEntries") |
| 108 | + void transactionManagerFromJndi(JndiEntry jndiEntry, InitialContext initialContext) throws NamingException { |
| 109 | + jndiEntry.register(initialContext); |
| 110 | + this.context = new AnnotationConfigApplicationContext(JtaAutoConfiguration.class); |
| 111 | + JtaTransactionManager transactionManager = this.context.getBean(JtaTransactionManager.class); |
| 112 | + if (jndiEntry.value instanceof UserTransaction) { |
| 113 | + assertThat(transactionManager.getUserTransaction()).isEqualTo(jndiEntry.value); |
| 114 | + assertThat(transactionManager.getTransactionManager()).isNull(); |
| 115 | + } |
| 116 | + else { |
| 117 | + assertThat(transactionManager.getUserTransaction()).isInstanceOf(UserTransactionAdapter.class); |
| 118 | + assertThat(transactionManager.getTransactionManager()).isEqualTo(jndiEntry.value); |
| 119 | + } |
| 120 | + } |
| 121 | + |
| 122 | + static List<Arguments> transactionManagerJndiEntries() { |
| 123 | + return Arrays.asList(Arguments.of(new JndiEntry("java:comp/UserTransaction", UserTransaction.class)), |
| 124 | + Arguments.of(new JndiEntry("java:appserver/TransactionManager", TransactionManager.class)), |
| 125 | + Arguments.of(new JndiEntry("java:pm/TransactionManager", TransactionManager.class)), |
| 126 | + Arguments.of(new JndiEntry("java:/TransactionManager", TransactionManager.class))); |
83 | 127 | }
|
84 | 128 |
|
85 | 129 | @Test
|
@@ -292,4 +336,79 @@ DataSource pooledDataSource(XADataSourceWrapper wrapper) throws Exception {
|
292 | 336 |
|
293 | 337 | }
|
294 | 338 |
|
| 339 | + private static final class JndiEntry { |
| 340 | + |
| 341 | + private final String name; |
| 342 | + |
| 343 | + private final Class<?> type; |
| 344 | + |
| 345 | + private final Object value; |
| 346 | + |
| 347 | + private JndiEntry(String name, Class<?> type) { |
| 348 | + this.name = name; |
| 349 | + this.type = type; |
| 350 | + this.value = mock(type); |
| 351 | + } |
| 352 | + |
| 353 | + private void register(InitialContext initialContext) throws NamingException { |
| 354 | + String[] components = this.name.split("/"); |
| 355 | + String subcontextName = components[0]; |
| 356 | + String entryName = components[1]; |
| 357 | + Context javaComp = initialContext.createSubcontext(subcontextName); |
| 358 | + JndiLoader loader = new JndiLoader(initialContext.getEnvironment()); |
| 359 | + Properties properties = new Properties(); |
| 360 | + properties.setProperty(entryName + "/type", this.type.getName()); |
| 361 | + properties.put(entryName + "/valueToConvert", this.value); |
| 362 | + loader.load(properties, javaComp); |
| 363 | + } |
| 364 | + |
| 365 | + @Override |
| 366 | + public String toString() { |
| 367 | + return this.name; |
| 368 | + } |
| 369 | + |
| 370 | + } |
| 371 | + |
| 372 | + private static final class JndiExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver { |
| 373 | + |
| 374 | + @Override |
| 375 | + public void beforeEach(ExtensionContext context) throws Exception { |
| 376 | + Namespace namespace = Namespace.create(getClass(), context.getUniqueId()); |
| 377 | + context.getStore(namespace).getOrComputeIfAbsent(InitialContext.class, (k) -> createInitialContext(), |
| 378 | + InitialContext.class); |
| 379 | + } |
| 380 | + |
| 381 | + private InitialContext createInitialContext() { |
| 382 | + try { |
| 383 | + return new InitialContext(); |
| 384 | + } |
| 385 | + catch (Exception ex) { |
| 386 | + throw new RuntimeException(); |
| 387 | + } |
| 388 | + } |
| 389 | + |
| 390 | + @Override |
| 391 | + public void afterEach(ExtensionContext context) throws Exception { |
| 392 | + Namespace namespace = Namespace.create(getClass(), context.getUniqueId()); |
| 393 | + InitialContext initialContext = context.getStore(namespace).remove(InitialContext.class, |
| 394 | + InitialContext.class); |
| 395 | + initialContext.removeFromEnvironment("org.osjava.sj.jndi.ignoreClose"); |
| 396 | + initialContext.close(); |
| 397 | + } |
| 398 | + |
| 399 | + @Override |
| 400 | + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) |
| 401 | + throws ParameterResolutionException { |
| 402 | + return InitialContext.class.isAssignableFrom(parameterContext.getParameter().getType()); |
| 403 | + } |
| 404 | + |
| 405 | + @Override |
| 406 | + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) |
| 407 | + throws ParameterResolutionException { |
| 408 | + Namespace namespace = Namespace.create(getClass(), extensionContext.getUniqueId()); |
| 409 | + return extensionContext.getStore(namespace).get(InitialContext.class); |
| 410 | + } |
| 411 | + |
| 412 | + } |
| 413 | + |
295 | 414 | }
|
0 commit comments