Below is a snippet from the camle-osgi example. I can obtain the camel context but how do I get the original spring application context? Or how am I supposed to get a reference to "mybean"?
MyRouteBuilder.java:
public class MyRouteBuilder extends RouteBuilder {
public static void main(String[] args) throws Exception{
new Main().run(args);
}
public void configure() {
// set up the transform bean
ModelCamelContext mc = getContext();//ok, I can get the camel context fine
//but how to get the spring context to get to "mybean"???
//set up routes
}
}
beans.xml:
<beans>
<camel:camelContext xmlns="http://camel.apache.org/schema/spring">
<package>org.apache.servicemix.examples.camel</package>
-----
</route>
</camel:camelContext>
<bean id="mybean" class="myclass"/>
</beans>
You should not use the spring context directly. Instead use the spring features to inject the beans you need.
Define the routebuilder as a bean in the spring context and use a setter and to inject myBean.
Keep the auto discovery and use annotations like #Autowired in the routebuilder to inject mybean.
A third option is to use getContext().getRegistry(). The registry allows to access all beans of the spring context by name or by type.
It would not be camel if we are already out of options :-)
So another options is to use the bean component of camel to access beans from the spring context: http://camel.apache.org/bean.html
Related
I have a question around the usage of new keyword being used when using java configuration in spring. What is the need of using new keyword
Refer below mentioned example:
Code implemented using Java Config
#Configuration
public class HelloWorldConfig {
#Bean
public HelloWorld helloWorld(){
return new HelloWorld();
}
}
The above code will be equivalent to the following XML configuration
<beans>
<bean id = "helloWorld" class = "com.test.HelloWorld" />
</beans>
In XML config, we do not use new keyword whereas in java config we are using new keyword. can someone please explain the difference
In the XML configuration, you explain to the system what class should be instanciated (there is a "new" but it is behind the scene) but in the Java Config you actually have to return an instance so that is why we use the 'new' keyword. 'new' simply creates an instance of your class.
The two examples shown in question are not really equivalent.
What the
<beans>
<bean id="helloWorld"
class="com.test.HelloWorld" />
</beans>
really does, is it tells Spring to instantiate class com.test.HelloWorld, and name the resulting bean "helloWorld".
Then the java-config approach is not really doing this. Instead this follows the factory-method pattern, when we tell Spring, that the return value of the method is the bean, and the method name is the name of that bean.
An equivalent of that in XML would be the mentioned factory-method approach, which in this case would look something like this:
<beans>
<bean id="helloWorldConfig"
class="com.test.HelloWorldConfig" />
<bean id="helloWorld"
factory-bean="helloWorldConfig"
factory-method="helloWorld" />
</beans>
Note that there are several approaches to factory-method. In the above, we are assuming, the `helloWorldConfig" is the factory, and we're specifying the method on that bean. Theare are cases with static factory methods too. See here for more examples.
<beans>
<bean id = "helloWorld" class = "com.test.HelloWorld" />
</beans>
This XML configurations tells Spring to "create an instance of com.test.HelloWorld and put it in the bean context with bean id helloWorld".
#Configuration
public class HelloWorldConfig {
#Bean
public HelloWorld helloWorld(){
return new HelloWorld();
}
}
In this Java configuration, we are returning an instance of com.test.HelloWorld. Because of the #Bean annotation, this instance is put into the bean context. As no specific bean id is given, the bean id is derived from the method hellowWorld() and thus becomes helloWorld.
As you can see, both configurations require an instance of com.test.HelloWorld. The XML configuration implicitly creates the instance whereas in the Java configuration you have to explicitly do it yourself.
For example, I have 3 beans in my spring configuration: A, B, C. And I want to create bean B and C as usual. And than (when all others beans were created) I want to ask spring to create bean A.
Any suggestion ?
Thanks.
Spring framework triggers a ContextRefreshedEvent once the contexts has been fully refreshed and all the configured beans have been created.
You could try to create a listener to catch that event and initialise bean A.
#Component
public class ContextRefreshedEventListener implements
ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
// Init your bean here
}
}
You should try #DependsOn adnotation
For example
<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
<property name="manager" ref="manager" />
</bean>
<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
I know it's not really a bean ordering answer, but maybe you can achieve your goal with a #PostConstruct method that will be called just after a bean is constructed, dependencies are injected and all properties are set.
best nas
Easier way to do this would be using #Lazy annotation to your bean. This makes your bean do not get initialized eagerly during context initialization. In simple words,your bean will get created when you ask for it, not before.
#Bean
#Lazy
public A beanA() {
//some code here
}
I noticed that if you define a bean with same id in two xml files, it would be overiden in the second file.
Say in file a.xml i have
<bean id="abc" />
Say in file b.xml i have
<bean id="abc" />
then the bean "abc" of b.xml is picked up. Is there a way in Spring to stop from overiding i.e should be unique no matter how many xml have the bean abc.
You can disable the feature to disallow beanoverriding by calling the setAllowBeanDefinitionOverriding and pass false. This has to be done early on before anything is loaded. You would either need to create your own custom ContextLoader for this or (if you are on Spring 3.1 or up) you can create an ApplicationContextInitializer and register this in your web.xml.
public class OverrideDisablingApplicationContextInitializer implements ApplicationContextInitializer {
public void void initialize(<? extends ConfigurableApplicationContext> applicationContext);
if (applicationContext instanceof AbstractRefreshableApplicationContext) {
(AbstractRefreshableApplicationContext (applicationContext)).setAllowBeanDefinitionOverriding(false);
}
}
in your web.xml add the following (for the ContextLoaderListener use an init-param for the DispatcherServlet when needed)
<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>your.package.here.OverrideDisablingApplicationContextInitializer<param-value>
</context-param>
From the top of my head this should disable the overriding behavior. If you use springs WebApplicationInitializer it is even easier as you are probably constructing the ApplicationContext yourself, you can then simply call the method directly and no ApplicationContextInitializer is needed.
Links
ApplicationContextInitializer javadoc
AbstractRefreshableApplicationContext.setAllowBeanDefinitionOverriding javadoc
Also:
final ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext();
ctx.setAllowBeanDefinitionOverriding(false);
ctx.setConfigLocations(shardContextImport);
ctx.setParent(refreshedEvent.getApplicationContext());
ctx.refresh();
I use org.springframework.web.jsf.el.SpringBeanFacesELResolver in my JSF + Spring application. Every backing bean needs an interface to be resolved. I guess that it's interface type of dependency injection.
#{bean.text}
public interface IBean {
String getText();
}
#Named
#Scope("session")
public class Bean implements IBean {
public String getText() {
return "Hello World!";
}
}
I would like to get rid of the interface. It's kind of bureaucracy for me. Is it possible?
I finally solved it. The problem was in beans with scope depending on HTTP (request, session). By default interfaces should be manually created. This can be avoided by using proxies.
If using component scan:
<context:component-scan base-package="..." scoped-proxy="targetClass" />
Or in bean definition:
<bean ...>
<aop:scoped-proxy>
</bean>
See chapter 4.5.4.5 Scoped beans as dependencies in Spring documentation. http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html
I think I've read every question and answer on Spring and autowiring a servlet, both here and at springsource.org, and I still can't get it working.
All I want to do is have the datasource automatically set in my servlets. I understand that the container creates the servlet and not Spring.
Here is code from my test servlet:
package mypackage.servlets;
imports go here...
#Service
public class TestServlet extends HttpServlet
{
private JdbcTemplate _jt;
#Autowired
public void setDataSource(DataSource dataSource)
{
_jt = new JdbcTemplate(dataSource);
}
etc etc
In my applicationContext.xml I have:
<context:annotation-config />
<context:component-scan base-package="mypackage.servlets />
<import resource="datasource.xml" />
and in my datasource.xml:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/db" />
If I can't get this working I'll just use WebApplicationContextUtils in the servlet's init method but I'd really like to make this work after all the reading I've been doing.
I'm using Spring 3, Java 1.6.
Thanks,
Paul
You need to replace your Servlets by Spring MVC contollers. Because Spring will not inject anything the classes (servlets) created by someone else then Spring itselfe (except #Configurable).
(To get an very simple example, take a look at the STS Spring Template Project: MVC).
What I wanted to do was get a DataSource reference in my Servlet for free, i.e. not calling a static getDatasource method on some class.
Here's what I learned and how I got it working:
Servlets cannot be configured or autowired by Spring. Servlets are created before Spring's app context is loaded. See issue SPR-7801: https://jira.springsource.org/browse/SPR-7801
What I did was create a DataSource in my applicationContext.xml and export that as a property:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/db" />
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="myDatasource">
<ref bean="dataSource"/>
</entry>
</map>
</property>
</bean>
In my servlet's init method I read the property:
public void init(ServletConfig config)
{
Object obj = config.getServletContext().getAttribute("myDatasource");
setDataSource((DataSource)obj);
}
public void setDataSource(DataSource datasource)
{
// do something here with datasource, like
// store it or make a JdbcTemplate out of it
}
If I'd been using DAOs instead of hitting the database from the servlets it would have been easy to wire them up for #Autowired by marking them #Configurable, and also be able to use #Transactional and other Spring goodies.