How can I achieve something similar to this:
<jee:jndi-lookup id="datasSource"
jndi-name="jdbc/dataSourceName" expected-type="javax.sql.DataSource" />
<tx:jta-transaction-manager/>
Using annotations?
#Configuration
#EnableTransactionManagement
public class AppConfig {
#Bean
public DataSource dataSource() {
// What goes here?
}
#Bean
public PlatformTransactionManager txManager() {
// What goes here?
}
}
I've seen a lot of examples with DataSourceTransactionManager and BasicDataSource, but I couldn't find a equivalent annotation driven configuration (that finds the container UserTransaction, etc).
The only way I am aware of is to replicate the behavior of namespace parsers of these custom namespaces.
So, <jee:jndi-lookup> is handled by org.springframework.ejb.config.JndiLookupBeanDefinitionParser and ultimate creates a bean which is an instance of JndiObjectFactoryBean with the passed in attributes.
Similarly, <tx:jta-transaction-manager/> is handled by org.springframework.transaction.config.JtaTransactionManagerBeanDefinitionParser and based on the runtime environment, returns a specific instance of class.
A neat feature of Spring 4 that you can use is #Conditional(reference here). With #Conditional and using a Spring-Boot Conditional implementation called ConditionalOnClass(reference here), you can replicate the behavior of <tx... something like this:
#Configuration
#ConditionalOnClass(name="weblogic.transaction.UserTransaction")
public class WebLogicTxMgrConfig {
#Bean
public JtaTransactionManager txManager() {
return new WebLogicJtaTransactionManager();
}
}
I know this is not a complete answer, but hopefully should help you create the relevant configuration.
Related
What I want to achieve
My objective is to have a transactional bean, instantiated twice (or more), and each time w/ a different TransactionManager (i.e. a different DB).
#Transactional
class MyReusableService {
...
}
#Configuration
class MyConfig {
// here I want to use `transactionManagerForDb1`
#Bean
public MyReusableService myReusableServiceForDb1() { ... }
// here I want to use `transactionManagerForDb2`
#Bean
public MyReusableService myReusableServiceForDb2() { ... }
}
What I observed
TransactionInterceptor is the piece that delegates to a TransactionManager (TM). I found it used in 2 ways:
Via #EnableJpaRepositories(... transactionManagerRef="..."). This mechanism relates a bit w/ what I want. But it doesn't use #Transactional at all. It finds all the repos. And it instantiates one TransactionInterceptor per repo.
Via #Transactional. Here, there is a single instance of TransactionInterceptor (TI). And at each invocation, it decides which TM to use by looking at the annotations (using caching of course). This TI is defined ProxyTransactionManagementConfiguration.
What I did
I defined my own TI:
#Configuration
public class MyConfiguration {
#SuppressWarnings("serial")
public static class MyTransactionInterceptor extends TransactionInterceptor {
...
}
#Bean
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new MyTransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
return interceptor;
}
}
This seem to work. The TI defined by Spring is no more instantiated. Mine is. And it is used.
My questions
Why does the above work? How did Spring know that I wanted to override it's TI? I was expecting to have 2 TIs, and fight to use the right one, maybe using #Primary. E.g. like here.
Is there maybe a cleaner way to achieve my objective? I cannot say I'm entirely satisfied, because I find the solution a bit intrusive. MyReusableService resides actually in a lib. And forcing the user to override the TI is not self contained.
I am trying to convert a XML based configuration to JAVA based configuration. Can someone please let me know the java annotation based configuration for the following
<jms:outbound-channel-adapter channel="requestChannel"
connection-factory="testConnectionFactory"
destination-name="${jms.queueName}"
message-converter="messageConverter"/>
I tried having a look at this Reference doc. But i am not able to understand how do I map the above xml to the annotation config.
#ServiceActivator(inputChannel="requestChannel")
#Bean
public MessageHandler outbound(JmsTemplate jmsTemplate) {
JmsSendingMessageHandler handler = new JmsSendingMessageHandler(jmsTemplate);
handler.setDestinationName(...);
...
return handler;
}
#Bean
public JmsTemplate jmsTemplate(ConnectionFactory jmsConnectionFactory) {
...
template.setMessageConverter(converter());
return template;
}
Then add the connection factory and converter beans.
EDIT
Also pay attention to Spring Integration Java DSL project, which provides the org.springframework.integration.dsl.jms.Jms Factory on the matter. You can find its usage in the JmsTests: https://github.com/spring-projects/spring-integration-java-dsl/blob/master/src/test/java/org/springframework/integration/dsl/test/jms/JmsTests.java
I was wondering if there was a sort of compromise that allowed you to emulate/leverage the Google Guice style EDSL way of writing modules which binds interfaces to implementations in Spring.
For example, say I had a Google Guice Module that looked like this:
public class BillingModule extends AbstractModule {
protected void configure() {
bind(BillingService.class).to(RealBillingService.class);
}
}
This binds the BillingService interface to the RealBillingService implementation.
One way that I think I can do utilizing Spring's Java configuration class is something that looks like this
#Configuration
public class BillingConfiguration {
#Bean
public BillingService getRealBillingService() {
return new RealBillingService();
}
}
I was wondering if there was a better way to do this or if this broke down with increasingly complex usage.
I really like Google Guice and how it does Dependency Injection but that's kind of all it does. Spring does a lot more (yes, its dependency injection mechanism is still not 'as-nice' as Guice) but undeniably has some great projects that we would like to utilize like Spring Data, Spring Data REST, etc. which eliminate the need for writing a ton of boilerplate code.
The way to do this is to use #Profile to include different implementations of the same interface.
A simple example would be DataSource. This can however easily be extended to any other interfaces with multiple implementations.
As an example:
#Configuration
public class LocalDataConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
}
and then for use in production:
#Configuration
#Profile("production")
public class JndiDataConfig {
#Bean
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
Then all you need to do is declare which profiles are active when you start your application context and #Inject/#Autowire DataSource where you need it.
I've used both Guice and Spring a fair bit. As far as I know, the spring usage you show in the question is the only way to achieve the same as the binding in Guice with Spring. If you need to inject dependencies you can always include those as arguments to the #Bean method and have spring inject them for you.
It's definitely not as clean but it works the same way. One key thing to watch out for is that the default scope in spring is Singleton rather than a new instance every time (spring calls this scope prototype)
I am working on a project with multiple spring configuration java classes. Many of them have beans from other config classes autowired in and then injected in the constructors of other beans.
To make this as flexible as possible, I have been using spring profiles to define which implementation of an interface to use in the case where multiple are available.
This works fine, but I was wondering if there was any way with Spring that you could define a default bean?
For example: If no bean of type Foo found on classpath, inject implementation Bar. Else, ignore Bar.
I have looked at this question: Spring 3: Inject Default Bean Unless Another Bean Present, and the solution shown with Java config would work fine if you knew the name of all of the beans, but in my case I will not know what the beans are called.
Does anybody know of a way this can be achieved?
Define the default as, well the default, just make sure that the name of the bean is the same, the one inside the profile will override the default one.
<beans>
<!-- The default datasource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
</bean>
<beans profile="jndi">
<jndi:lookup id="dataSource" jndi-name="jdbc/db" />
</beans>
</beans>
This construct would also work with Java based config.
#Configuration
public DefaultConfig {
#Bean
public DataSource dataSource() { ... }
#Configuration
#Profile("jndi")
public static class JndiConfig {
#Bean
public DataSource dataSource() { ... // JNDI lookup }
}
}
When using java based configuration you can also specify a default and in another configuration add another bean of that type and annotate it with #Primary. When multiple instances are found the one with #Primary should be used.
#Configuration
public DefaultConfig {
#Bean
public DataSource dataSource() { ... }
}
#Configuration
#Profile("jndi")
public class JndiConfig {
#Bean
#Primary
public DataSource jndiDataSource() { ... // JNDI lookup }
}
According to Spring's Documentation Configuring AspectJ aspects using Spring IoC in order to configure an aspect for Spring IOC, the following has to be added to the xml configuration:
<bean id="profiler" class="com.xyz.profiler.Profiler"
factory-method="aspectOf">
<property name="profilingStrategy" ref="jamonProfilingStrategy"/>
</bean>
As suggested by #SotiriosDelimanolis, rewriting this as the following in JavaConfig should to work:
#Bean
public com.xyz.profiler.Profiler profiler() {
com.xyz.profiler.Profiler profiler = com.xyz.profiler.Profiler.aspectOf();
profiler.setProfilingStrategy(jamonProfilingStrategy()); // assuming you have a corresponding #Bean method for that bean
return profiler;
}
However, this only seems to work if the Profiler aspect is written in native aspectj .aj syntax. If it is written in Java and annotated with #Aspect, I get the following error message:
The method aspectOf() is undefined for the type Profiler
Is there an equivalent way of writing this using JavaConfig for aspects written with #AspectJ syntax?
Turns out that there is an org.aspectj.lang.Aspects class to provide for specifically this purpose. It appears that the aspectOf() method is added by the LTW which is why it works fine in XML configuration, but not at compile time.
To get around this limitation, org.aspectj.lang.Aspects provides a aspectOf() method:
#Bean
public com.xyz.profiler.Profiler profiler() {
com.xyz.profiler.Profiler profiler = Aspects.aspectOf(com.xyz.profiler.Profiler.class);
profiler.setProfilingStrategy(jamonProfilingStrategy()); // assuming you have a corresponding #Bean method for that bean
return profiler;
}
Hope this helps someone else in the future.
Is there an equivalent way of writing this using JavaConfig?
Almost always.
#Bean
public com.xyz.profiler.Profiler profiler() {
com.xyz.profiler.Profiler profiler = com.xyz.profiler.Profiler.aspectOf();
profiler.setProfilingStrategy(jamonProfilingStrategy()); // assuming you have a corresponding #Bean method for that bean
return profiler;
}
The factory-method is explained in the documentation in Instantiation with a static factory method.