Create spring-boot-tx module

This commit is contained in:
Andy Wilkinson
2025-03-18 13:22:09 +00:00
committed by Phillip Webb
parent 524db779e5
commit 5360ef8321
74 changed files with 136 additions and 76 deletions

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.transaction.autoconfigure;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.transaction.ConfigurableTransactionManager;
import org.springframework.transaction.TransactionExecutionListener;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link ExecutionListenersTransactionManagerCustomizer}.
*
* @author Andy Wilkinson
*/
class ExecutionListenersTransactionManagerCustomizerTests {
@Test
void whenTransactionManagerIsCustomizedThenExecutionListenersAreAddedToIt() {
TransactionExecutionListener listener1 = mock(TransactionExecutionListener.class);
TransactionExecutionListener listener2 = mock(TransactionExecutionListener.class);
ConfigurableTransactionManager transactionManager = mock(ConfigurableTransactionManager.class);
new ExecutionListenersTransactionManagerCustomizer(List.of(listener1, listener2)).customize(transactionManager);
then(transactionManager).should().addListener(listener1);
then(transactionManager).should().addListener(listener2);
}
}

View File

@@ -0,0 +1,329 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.transaction.autoconfigure;
import java.util.UUID;
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.LazyInitializationExcludeFilter;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.ReactiveTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.aspectj.AbstractTransactionAspect;
import org.springframework.transaction.reactive.TransactionalOperator;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link TransactionAutoConfiguration}.
*
* @author Stephane Nicoll
* @author Phillip Webb
*/
class TransactionAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(TransactionAutoConfiguration.class));
@Test
void whenThereIsNoPlatformTransactionManagerNoTransactionTemplateIsAutoConfigured() {
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(TransactionTemplate.class));
}
@Test
void whenThereIsASinglePlatformTransactionManagerATransactionTemplateIsAutoConfigured() {
this.contextRunner.withUserConfiguration(SinglePlatformTransactionManagerConfiguration.class).run((context) -> {
PlatformTransactionManager transactionManager = context.getBean(PlatformTransactionManager.class);
TransactionTemplate transactionTemplate = context.getBean(TransactionTemplate.class);
assertThat(transactionTemplate.getTransactionManager()).isSameAs(transactionManager);
});
}
@Test
void whenThereIsASingleReactiveTransactionManagerATransactionalOperatorIsAutoConfigured() {
this.contextRunner.withUserConfiguration(SingleReactiveTransactionManagerConfiguration.class).run((context) -> {
ReactiveTransactionManager transactionManager = context.getBean(ReactiveTransactionManager.class);
TransactionalOperator transactionalOperator = context.getBean(TransactionalOperator.class);
assertThat(transactionalOperator).extracting("transactionManager").isSameAs(transactionManager);
});
}
@Test
void whenThereAreBothReactiveAndPlatformTransactionManagersATemplateAndAnOperatorAreAutoConfigured() {
this.contextRunner
.withUserConfiguration(SinglePlatformTransactionManagerConfiguration.class,
SingleReactiveTransactionManagerConfiguration.class)
.withPropertyValues("spring.datasource.url:jdbc:h2:mem:" + UUID.randomUUID())
.run((context) -> {
PlatformTransactionManager platformTransactionManager = context
.getBean(PlatformTransactionManager.class);
TransactionTemplate transactionTemplate = context.getBean(TransactionTemplate.class);
assertThat(transactionTemplate.getTransactionManager()).isSameAs(platformTransactionManager);
ReactiveTransactionManager reactiveTransactionManager = context
.getBean(ReactiveTransactionManager.class);
TransactionalOperator transactionalOperator = context.getBean(TransactionalOperator.class);
assertThat(transactionalOperator).extracting("transactionManager").isSameAs(reactiveTransactionManager);
});
}
@Test
void whenThereAreSeveralPlatformTransactionManagersNoTransactionTemplateIsAutoConfigured() {
this.contextRunner.withUserConfiguration(SeveralPlatformTransactionManagersConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean(TransactionTemplate.class));
}
@Test
void whenThereAreSeveralReactiveTransactionManagersNoTransactionOperatorIsAutoConfigured() {
this.contextRunner.withUserConfiguration(SeveralReactiveTransactionManagersConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean(TransactionalOperator.class));
}
@Test
void whenAUserProvidesATransactionTemplateTheAutoConfiguredTemplateBacksOff() {
this.contextRunner.withUserConfiguration(CustomPlatformTransactionManagerConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(TransactionTemplate.class);
assertThat(context.getBean("transactionTemplateFoo")).isInstanceOf(TransactionTemplate.class);
});
}
@Test
void whenAUserProvidesATransactionalOperatorTheAutoConfiguredOperatorBacksOff() {
this.contextRunner
.withUserConfiguration(SingleReactiveTransactionManagerConfiguration.class,
CustomTransactionalOperatorConfiguration.class)
.run((context) -> {
assertThat(context).hasSingleBean(TransactionalOperator.class);
assertThat(context.getBean("customTransactionalOperator")).isInstanceOf(TransactionalOperator.class);
});
}
@Test
void transactionNotManagedWithNoTransactionManager() {
this.contextRunner.withUserConfiguration(BaseConfiguration.class)
.run((context) -> assertThat(context.getBean(TransactionalService.class).isTransactionActive()).isFalse());
}
@Test
void transactionManagerUsesCglibByDefault() {
this.contextRunner.withUserConfiguration(PlatformTransactionManagersConfiguration.class).run((context) -> {
assertThat(context.getBean(AnotherServiceImpl.class).isTransactionActive()).isTrue();
assertThat(context.getBeansOfType(TransactionalServiceImpl.class)).hasSize(1);
});
}
@Test
void transactionManagerCanBeConfiguredToJdkProxy() {
this.contextRunner.withUserConfiguration(PlatformTransactionManagersConfiguration.class)
.withPropertyValues("spring.aop.proxy-target-class=false")
.run((context) -> {
assertThat(context.getBean(AnotherService.class).isTransactionActive()).isTrue();
assertThat(context).doesNotHaveBean(AnotherServiceImpl.class);
assertThat(context).doesNotHaveBean(TransactionalServiceImpl.class);
});
}
@Test
void customEnableTransactionManagementTakesPrecedence() {
this.contextRunner
.withUserConfiguration(CustomTransactionManagementConfiguration.class,
PlatformTransactionManagersConfiguration.class)
.withPropertyValues("spring.aop.proxy-target-class=true")
.run((context) -> {
assertThat(context.getBean(AnotherService.class).isTransactionActive()).isTrue();
assertThat(context).doesNotHaveBean(AnotherServiceImpl.class);
assertThat(context).doesNotHaveBean(TransactionalServiceImpl.class);
});
}
@Test
void excludesAbstractTransactionAspectFromLazyInit() {
this.contextRunner.withUserConfiguration(AspectJTransactionManagementConfiguration.class).run((context) -> {
LazyInitializationExcludeFilter filter = context.getBean(LazyInitializationExcludeFilter.class);
assertThat(filter.isExcluded(null, null, AbstractTransactionAspect.class)).isTrue();
});
}
@Configuration
static class SinglePlatformTransactionManagerConfiguration {
@Bean
PlatformTransactionManager transactionManager() {
return mock(PlatformTransactionManager.class);
}
}
@Configuration
static class SingleReactiveTransactionManagerConfiguration {
@Bean
ReactiveTransactionManager reactiveTransactionManager() {
return mock(ReactiveTransactionManager.class);
}
}
@Configuration(proxyBeanMethods = false)
static class SeveralPlatformTransactionManagersConfiguration {
@Bean
PlatformTransactionManager transactionManagerOne() {
return mock(PlatformTransactionManager.class);
}
@Bean
PlatformTransactionManager transactionManagerTwo() {
return mock(PlatformTransactionManager.class);
}
}
@Configuration(proxyBeanMethods = false)
static class SeveralReactiveTransactionManagersConfiguration {
@Bean
ReactiveTransactionManager reactiveTransactionManager1() {
return mock(ReactiveTransactionManager.class);
}
@Bean
ReactiveTransactionManager reactiveTransactionManager2() {
return mock(ReactiveTransactionManager.class);
}
}
@Configuration(proxyBeanMethods = false)
static class CustomPlatformTransactionManagerConfiguration {
@Bean
TransactionTemplate transactionTemplateFoo(PlatformTransactionManager transactionManager) {
return new TransactionTemplate(transactionManager);
}
@Bean
PlatformTransactionManager transactionManagerFoo() {
return mock(PlatformTransactionManager.class);
}
}
@Configuration(proxyBeanMethods = false)
static class CustomTransactionalOperatorConfiguration {
@Bean
TransactionalOperator customTransactionalOperator() {
return mock(TransactionalOperator.class);
}
}
@Configuration(proxyBeanMethods = false)
static class BaseConfiguration {
@Bean
TransactionalService transactionalService() {
return new TransactionalServiceImpl();
}
@Bean
AnotherServiceImpl anotherService() {
return new AnotherServiceImpl();
}
}
@Configuration(proxyBeanMethods = false)
@Import(BaseConfiguration.class)
static class PlatformTransactionManagersConfiguration {
@Bean
DataSourceTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
DataSource dataSource() {
return DataSourceBuilder.create()
.driverClassName("org.hsqldb.jdbc.JDBCDriver")
.url("jdbc:hsqldb:mem:tx")
.username("sa")
.build();
}
}
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = false)
static class CustomTransactionManagementConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
static class AspectJTransactionManagementConfiguration {
}
interface TransactionalService {
@Transactional
boolean isTransactionActive();
}
static class TransactionalServiceImpl implements TransactionalService {
@Override
public boolean isTransactionActive() {
return TransactionSynchronizationManager.isActualTransactionActive();
}
}
interface AnotherService {
boolean isTransactionActive();
}
static class AnotherServiceImpl implements AnotherService {
@Override
@Transactional
public boolean isTransactionActive() {
return TransactionSynchronizationManager.isActualTransactionActive();
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.transaction.autoconfigure;
import java.util.Collections;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link TransactionManagerCustomizationAutoConfiguration}.
*
* @author Andy Wilkinson
*/
class TransactionManagerCustomizationAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(TransactionManagerCustomizationAutoConfiguration.class));
@Test
void autoConfiguresTransactionManagerCustomizers() {
this.contextRunner.run((context) -> {
TransactionManagerCustomizers customizers = context.getBean(TransactionManagerCustomizers.class);
assertThat(customizers).extracting("customizers")
.asInstanceOf(InstanceOfAssertFactories.LIST)
.hasSize(2)
.hasAtLeastOneElementOfType(TransactionProperties.class)
.hasAtLeastOneElementOfType(ExecutionListenersTransactionManagerCustomizer.class);
});
}
@Test
void autoConfiguredTransactionManagerCustomizersBacksOff() {
this.contextRunner.withUserConfiguration(CustomTransactionManagerCustomizersConfiguration.class)
.run((context) -> {
TransactionManagerCustomizers customizers = context.getBean(TransactionManagerCustomizers.class);
assertThat(customizers).extracting("customizers")
.asInstanceOf(InstanceOfAssertFactories.LIST)
.isEmpty();
});
}
@Configuration(proxyBeanMethods = false)
static class CustomTransactionManagerCustomizersConfiguration {
@Bean
TransactionManagerCustomizers customTransactionManagerCustomizers() {
return TransactionManagerCustomizers.of(Collections.<TransactionManagerCustomizer<?>>emptyList());
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.transaction.autoconfigure;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link TransactionManagerCustomizers}.
*
* @author Phillip Webb
*/
class TransactionManagerCustomizersTests {
@Test
void customizeWithNullCustomizersShouldDoNothing() {
TransactionManagerCustomizers.of(null).customize(mock(TransactionManager.class));
}
@Test
void customizeShouldCheckGeneric() {
List<TestCustomizer<?>> list = new ArrayList<>();
list.add(new TestCustomizer<>());
list.add(new TestJtaCustomizer());
TransactionManagerCustomizers customizers = TransactionManagerCustomizers.of(list);
customizers.customize(mock(PlatformTransactionManager.class));
customizers.customize(mock(JtaTransactionManager.class));
assertThat(list.get(0).getCount()).isEqualTo(2);
assertThat(list.get(1).getCount()).isOne();
}
static class TestCustomizer<T extends PlatformTransactionManager> implements TransactionManagerCustomizer<T> {
private int count;
@Override
public void customize(T transactionManager) {
this.count++;
}
int getCount() {
return this.count;
}
}
static class TestJtaCustomizer extends TestCustomizer<JtaTransactionManager> {
}
}

View File

@@ -0,0 +1,207 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.transaction.jta.autoconfigure;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import jakarta.transaction.TransactionManager;
import jakarta.transaction.UserTransaction;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.osjava.sj.loader.JndiLoader;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.transaction.jta.UserTransactionAdapter;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link JtaAutoConfiguration}.
*
* @author Josh Long
* @author Phillip Webb
* @author Andy Wilkinson
* @author Kazuki Shimizu
* @author Nishant Raut
*/
@ClassPathExclusions("jetty-jndi-*.jar")
class JtaAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
@AfterEach
void closeContext() {
if (this.context != null) {
this.context.close();
}
}
@ParameterizedTest
@ExtendWith(JndiExtension.class)
@MethodSource("transactionManagerJndiEntries")
void transactionManagerFromJndi(JndiEntry jndiEntry, InitialContext initialContext) throws NamingException {
jndiEntry.register(initialContext);
this.context = new AnnotationConfigApplicationContext(JtaAutoConfiguration.class);
JtaTransactionManager transactionManager = this.context.getBean(JtaTransactionManager.class);
if (jndiEntry.value instanceof UserTransaction) {
assertThat(transactionManager.getUserTransaction()).isEqualTo(jndiEntry.value);
assertThat(transactionManager.getTransactionManager()).isNull();
}
else {
assertThat(transactionManager.getUserTransaction()).isInstanceOf(UserTransactionAdapter.class);
assertThat(transactionManager.getTransactionManager()).isEqualTo(jndiEntry.value);
}
}
static List<Arguments> transactionManagerJndiEntries() {
return Arrays.asList(Arguments.of(new JndiEntry("java:comp/UserTransaction", UserTransaction.class)),
Arguments.of(new JndiEntry("java:appserver/TransactionManager", TransactionManager.class)),
Arguments.of(new JndiEntry("java:pm/TransactionManager", TransactionManager.class)),
Arguments.of(new JndiEntry("java:/TransactionManager", TransactionManager.class)));
}
@Test
void customTransactionManager() {
this.context = new AnnotationConfigApplicationContext(CustomTransactionManagerConfig.class,
JtaAutoConfiguration.class);
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.context.getBean(JtaTransactionManager.class));
}
@Test
@ExtendWith(JndiExtension.class)
void disableJtaSupport(InitialContext initialContext) throws NamingException {
new JndiEntry("java:comp/UserTransaction", UserTransaction.class).register(initialContext);
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.jta.enabled:false").applyTo(this.context);
this.context.register(JtaAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeansOfType(JtaTransactionManager.class)).isEmpty();
}
@Configuration(proxyBeanMethods = false)
static class CustomTransactionManagerConfig {
@Bean
org.springframework.transaction.TransactionManager testTransactionManager() {
return mock(org.springframework.transaction.TransactionManager.class);
}
}
private static final class JndiEntry {
private final String name;
private final Class<?> type;
private final Object value;
private JndiEntry(String name, Class<?> type) {
this.name = name;
this.type = type;
this.value = mock(type);
}
private void register(InitialContext initialContext) throws NamingException {
String[] components = this.name.split("/");
String subcontextName = components[0];
String entryName = components[1];
Context javaComp = initialContext.createSubcontext(subcontextName);
JndiLoader loader = new JndiLoader(initialContext.getEnvironment());
Properties properties = new Properties();
properties.setProperty(entryName + "/type", this.type.getName());
properties.put(entryName + "/valueToConvert", this.value);
loader.load(properties, javaComp);
}
@Override
public String toString() {
return this.name;
}
}
private static final class JndiExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver {
@Override
public void beforeEach(ExtensionContext context) throws Exception {
Namespace namespace = Namespace.create(getClass(), context.getUniqueId());
context.getStore(namespace)
.getOrComputeIfAbsent(InitialContext.class, (k) -> createInitialContext(), InitialContext.class);
}
private InitialContext createInitialContext() {
try {
return new InitialContext();
}
catch (Exception ex) {
throw new RuntimeException();
}
}
@Override
public void afterEach(ExtensionContext context) throws Exception {
Namespace namespace = Namespace.create(getClass(), context.getUniqueId());
InitialContext initialContext = context.getStore(namespace)
.remove(InitialContext.class, InitialContext.class);
initialContext.removeFromEnvironment("org.osjava.sj.jndi.ignoreClose");
initialContext.close();
}
@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
throws ParameterResolutionException {
return InitialContext.class.isAssignableFrom(parameterContext.getParameter().getType());
}
@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
throws ParameterResolutionException {
Namespace namespace = Namespace.create(getClass(), extensionContext.getUniqueId());
return extensionContext.getStore(namespace).get(InitialContext.class);
}
}
}

View File

@@ -0,0 +1,5 @@
java.naming.factory.initial = org.osjava.sj.SimpleJndiContextFactory
org.osjava.sj.delimiter = /
org.osjava.sj.jndi.shared = true
org.osjava.sj.root = src/test/resources/simple-jndi
org.osjava.sj.jndi.ignoreClose = true