How to handle new implementation when using AutoWire in spring? - java

In the grails doc, I read (something along the lines) that the implementation of a server class will bu automatically wired based on the naming convention.
If this is true, then how would one go about overriding this behavior down the road say if you have a new implementation?
do we have options? like:
use #annotations
if you don't want to re-compile, add the entry to the xml

I am assuming "server class" was meant to be typed as "service class" and "bu"->"be"?
If those assumptions are correct: yes, they are autowired.
You create a grails service called UserService in your grails-app/services directory, you can inject it into a controller using:
def userService
You can override this behavior using the Spring DSL in the resources.groovy file in your grails-app/conf/spring directory. Or if you prefer XML, you can add a resources.xml file in grails-app/conf/spring to configure your Spring Beans.

Related

Spring custom autowiring

I have a project where I use heavily autowiring, e.g.
#Component("componentA")
public class ComponentAImpl implements ComponentA
#Component("componentB")
public class ComponentBImpl implements ComponentB {
#Autowired
private ComponentA componentA;
}
But I want customer to extend all the classes, so ideally they would just add a single jar into the classpath the the extended class should be used instead of the original one.
What I think would be great if they could just set a different name for the bean, e.g.
#component("componentA-custom)
I just need some way to customize the autowire process to look for a bean with "-custom" at the end and load it instead of the original bean.
Is there any way to do that?
Any help appreciated.
Thank you,
Mariusz
I found a solution, there is
#Primary
annotation that can be used to specify that the custom code added should be loaded instead of the original code.
What you are looking for is something similiar to this.
This should help you solve your problem.
If you need to get the bean name, you can inject in an instance of applicationContext which will get you the correct bean name (through a reverse lookup). or force all beans (ComponentA and CustomImplementation) to implement BeanNameAware
What You are asking about can be done via #Qualifier annotation, but it cannot generate bean names dynamically.
To allow external beans, You will need to create XML configuration for this, as it overrides annotation - based configuration. Your customers would have to provide:
New beans
XML configuration for your application that uses the new beans.

What is the proper way to have a "singleton" in Spring 4?

I have a java file "DatabaseMan.java" that helps connect to a database and connects helper functions. How can I make it such that it is created once for the life of my spring application, and I can call of its methods "getAllRows" for example, in each of my other resource classes?
Should I be declaring a bean in my Application.java or using some sort of annotation on my "DatabaseMan" class to indicate that it is "injectable"/"resusable"?
I see the following Spring3 example:
http://www.mkyong.com/spring3/spring-3-javaconfig-example/
The issue is, do I have to include this within every single resource:
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
HelloWorld obj = (HelloWorld) context.getBean("helloBean");
obj.printHelloWorld("Spring3 Java Config");
Is there a better way to get to the "HelloWorld" with less code and more annotation in Spring 4?
Remember, the ApplicationContext is a container to manage all your beans and their inter-dependencies. It is the entry point to your application. Once you've set it up, all the managed objects are linked up and ready to go.
Is there a better way to get to the "HelloWorld" with less code and more annotation in Spring 4?
It depends where you want to get it. If you want to get it from outside the ApplicationContext, then you need to do what you did. If you want to get into another bean, just inject it and the ApplicationContext will do the rest.
#Component
class SomeOtherBean {
#Autowired
private HelloWorld helloWorldBean;
// do something with it
}

Spring Test: better use XML configuration over annotations?

I'm learning Spring and looking at using Spring Test for my web app (JQuery/CXF/Hibernate). I have been using annotations to wire up my beans and noticed that this sometimes got into the way of polymorphism. For example I have a GenericDAO extended by all DAOs. It is also a concrete class used by simple services, so when I wired it for one of those services, ALL other DAOs became candidates for runtime wiring (because of polymorphism). I could solve that by wiring explicitly by type: #Resource(type= GenericDaoImpl.class), but this goes against the best practice of coding to interfaces ..
Now I want to create unit tests using a MockGenericDaoImpl, and integration tests using GenericDaoImpl. How will I override the annotations? I'm guessing the best approach is to stick to XML-based wiring, so that I can have several versions of beans.xml, one for prod, one for unit tests, one for integration tests, and possibly split them into parallel sub-files, as needed. Isn't this approach more flexible than depending on annotations that either scan to guess the appropriate candidate, or constrain polymorphism?
Can someone give me broad directions on how to organize my test configuration setup? Thank you!
How about using #Configuration class? If you're not familiar with this method - you can declare a class that replaces the XML context file and looks something like this:
#Configuration
#ComponentScan({ "com.project.dao"})
public class TestConfiguration {
#Bean
public GenericDao getGenericDao() {
return new MockGenericDaoImpl();
}
}
In the #ComponentScan annotation just put the relevant packages to scan. This way you're very flexible with the beans you're creating and the way to create them. You can injects mock to the beans whatever way you'd like.
Also you can create several test configurations, each configuration for a different purpose. In order to load the context you need to put this annotation on your test class:
#ContextConfiguration(classes={TestConfiguration .class})
Using XML configuration files prevent you from depending on Spring dependencies. You can replace it with another DI framework(maybe Guice, but this is not realistic for big projects I know). Using XML configuration files enables you to code cleanly.
I hate XML but I hate existence of not-business-logic-specific things in my code more.
I see you know how to overcome the test issues using XML configuration files. I will try to show how to overcome duplication of implementations(one real one mock implementation) problems using annotations.
You can define your beans via annotations. You can select implementation using aliases:
project.dev.properties:
my.project.dao.xDao=xDaoJpaBean
project.test.properties:
my.project.dao.xDao=xDaoMockBean
<alias name="${my.project.dao.xDao}" alias="xDao"/>
#Autowired
#Qualifier("xDao")
protected XDao xDao;
So you can select your implementation just using your properties file. If you want to use Annotations purely you can do this as well:
#Autowired
#Qualifier("${my.project.dao.xDao}")
protected XDao xDao;
Your build environment will specify which properties file to load, in return your bean will be assigned.

Conditionally creating beans in spring

Right now I'm exposing the service layer of my application using spring remoting's RMI/SOAP/JMS/Hessian/Burlap/HttpInvoker exporters. What I'd like is to allow the user to somehow define which of these remoting mechanisms they'd like enabled (rather than enabling all of them), then only create those exporter beans.
I was hoping that spring's application context xml's had support for putting in conditional blocks around portions of the xml. However, from what I've seen so far there's nothing in the standard spring distribution that allows you to do something like this.
Are there any other ways to achieve what I'm trying to do?
I am going to assume that you are looking to configure your application based on your environment, as in... for production I want to use this beans, in dev these other ...
As Ralph is saying, since Spring 3.1 you have profiles... But the key, is that you understand that you should put your environment based beans in different configuration files... so you could have something like dev-beans.xml, prod-beans.xml... Then in your main spring file, then you just invoke the appropriate one based on the environment that you are using... So profiles are only technique to do so... But you can also use other techniques, like have a system environmental variable, or pass a parameter in your build to decide which beans you want to use
You could realize this by using a Spring #Configuration bean, so you can construct your beans in java code. (see http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-java)
#Configuration
public class AppConfig {
#Bean
public MyService myService() {
if ( userSettingIshessian ) {
return new HessianExporter();
}else {
return new BurlapExporter();
}
}
}
Of course you need to get the user setting from somewhere, a system parameter would be easy, or config file, or something else.
Spring 3.1 has the concept of Profiles. My you can use them.

Spring Injecting into Struts RequestProcessor

I wrote a custom Struts RequsetProcessor for my application that is manually fetching some references from Spring. It is working just fine, but I would like to do the "right" thing and inject everything I need at construction time.
Is there a way to define a custom Struts RequestProcessor in a way that I can inject Spring objects into it when Struts instantiates this RequestProcessor?
The short answer is "NO". The long answer is "kind of":
Assuming Struts is integrated with Spring in your application via ContextLoaderPlugin, you can do one of two things:
A) Create a "ProcessorContext" bean (or whatever you want to call it) that you would define in your Spring context and access from your custom request processor by obtaining it from Spring's context (which you can get via WebApplicationContextUtils.getWebApplicationContext(getServletContext())).
B) If your custom processor extends Spring's DelegatingRequestProcessor or DelegatingTilesRequestProcessor you can instead write a new request processor that would do what you want functionality-wise, bind it to Spring context with all your dependencies and then extend DelegatingRequestProcessor or DelegatingTilesRequestProcessor to get it from context (either via type or id) and delegate to it. This is essentially an extension of (A) but it delegates all Spring's plumbing to Spring's request processor extension leaving your custom processor Spring-independent.
Spring / Struts integration is described in detail here.

Categories