Inject external object in a spring bean - spring

I have a noob spring question.
if i have a bean that is dependent on google's gdata api jars. How I represent this in a beans.xml file?

<bean class="com.google.foo.bar.ExternalClass" id="yourExternalBeanName" />
Then you can inject this 3rd party bean in your classes. With XML:
<property name="yourProperty" ref="yourExternalBeanName" />
or annotations:
#Inject
private ExternalClass yourProperty;

Related

Xml configuration for JdbcChannelMessageStore in a Spring Boot project with Spring Data JPA

I am very new to Spring Integration and would like to use a queue channel which is backed by a JdbcChannelMessageStore.
As our project uses Spring Boot with Spring Data JPA, I would like to have an integration-context.xml configuration where the existing data base connection is reused. However I struggle to make it work.
Unfortunately I cannot find any example projects where JdbcChannelMessageStore is used. Could anyone provide some good example implementations for this?
Thanks a lot in advance.
P.S.: Here is my last integration-context.xml version:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<int:channel id="outgoingChannel">
<int:queue message-store="outgoingMessageChannelStore"/>
</int:channel>
<bean id="dp"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${spring.datasource.password}" />
<property name="username" value="${spring.datasource.username}" />
<property name="password" value="${spring.datasource.password}" />
</bean>
<bean id="outgoingMessageChannelStore" class="org.springframework.integration.jdbc.store.JdbcChannelMessageStore">
<property name="dataSource" ref="dp"/>
<property name="channelMessageStoreQueryProvider" ref="jdbcChannelMessageStoreQueryProvider"/>
<property name="region" value="TX_TIMEOUT"/>
<property name="usingIdCache" value="true"/>
</bean>
<bean id="jdbcChannelMessageStoreQueryProvider" class="org.springframework.integration.jdbc.store.channel.OracleChannelMessageStoreQueryProvider" />
<int:transaction-synchronization-factory id="jdbcChannelMessageStoreFactory">
<int:after-commit expression="#jdbcChannelMessageStore.removeFromIdCache(headers.id.toString())" />
<int:after-rollback expression="#jdbcChannelMessageStore.removeFromIdCache(headers.id.toString())" />
</int:transaction-synchronization-factory>
</beans>
With this I am getting the following Exception at startup:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
...
Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
Well, since you say that you also use Spring Boot, you probably miss the fact that it auto-configure a DataSource bean for us. Having that dp bean in your config it just neglects that auto-configuration and tries to apply it everywhere you need DataSource, like that Hibernate auto-configuration.
What you really need is exactly opposite - you need to reuse an auto-configured DataSource for this Spring Integration config. Of course, if your JdbcChannelMessageStore is going to rely on the same data base as menitoned Spring Data JPA.
So, what you need is just remove that dp bean definition and use a dataSource name for the <property name="dataSource" in the outgoingMessageChannelStore bean definition.
Some remarks:
We don't need usingIdCache with Oracle and therefore no need in that jdbcChannelMessageStoreFactory to deal with the cache. And that even covered in JavaDocs:
* <p>If using the provided
* {#link org.springframework.integration.jdbc.store.channel.OracleChannelMessageStoreQueryProvider},
* don't set {#link #usingIdCache}
* to true, as the Oracle query will ignore locked rows.</p>
Try to configure Spring Integration with Java & Annotation Configuration (or even Java DSL). This way you won't be tied with a bean name (like that dataSource) and just will have a bean method argument injection for plain DataSource type and Spring container will inject for you an auto-configured bean.

Prevent Spring from meddling with CDI annotations even for factory created instances

I have a legacy product's JAR that contain Spring (4.3.8) managed classes. I need to integrate it with CDI (JavaEE 7).
I have an interface from the legacy JAR, that is implemented by a CDI bean. The CDI bean is requested from the CDI BeanManager and returned from a factory method. The factory method is registered inside Spring XML and works as expected.
The problem occurs, when a Spring bean of the legacy JAR depends on the implemented interface. Spring than injects the CDI implementation instance and scans the class it for known annotations, namingly #Inject. It then tries to resolve the dependency, which doesn't work since the dependency is not available to Spring.
I already tweaked context:property-placeholder excludes, but that changes nothing.
So how can I tell Spring to stop trying to inject something in my factory produced bean instance?
I finally was able to solve (work around) the problem. I had to remove all CDI-Annotations in the legacy JAR (by replacining them with their Spring counterparts), so spring would any longer work.
Then I added the following XML block to the applicationContext.xml of my CDI WAR:
<context:component-scan annotation-config="false" base-package="com.example">
</context:component-scan>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
<property name="autowiredAnnotationTypes">
<set>
<value>org.springframework.beans.factory.annotation.Autowired</value>
<value>org.springframework.beans.factory.annotation.Value</value>
</set>
</property>
</bean>
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>org.springframework.beans.factory.annotation.Qualifier</value>
</set>
</property>
</bean>
Basically that drops the support for #Inject, etc. from Spring and leaves it where it belongs: CDI.
It's a bit easier.
AutowiredAnnotationBeanPostProcessor is already a bean, so you can configure it before Spring starts to scan with a ServletContextListener to exclude #Inject annotations. At least from Spring 4.1+, AutowiredAnnotationBeanPostProcessor has a method setAutowiredAnnotationTypes, e.g.:
#WebListener
public class ApplicationConfigListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
ApplicationContext appCtx = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<Class<? extends Annotation>>();
AutowiredAnnotationBeanPostProcessor bean = appCtx.getBean(AutowiredAnnotationBeanPostProcessor.class);
autowiredAnnotationTypes.add(Autowired.class);
autowiredAnnotationTypes.add(Value.class);
bean.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
}
}
You could use a SpringBeanAutowiringInterceptor too.
This is explained here.

Refer a property of another bean in Spring 2.5.X

In Spring 3.0 and higher it is possible to refer a property of another bean as below.
<bean id="a" class="A">
<property name="list"
value="#{b.list}"/>
</bean>
Is there a way I can refer property of another bean in Spring 2.5.1.
Note that Spring Expression integrated after Spring 3.0
Spring is a framework for dependency injection and not for value injection. If your bean a has dependency on bean b for its creation, then why not inject the bean b in bean a.
Spring do give limited feature for injecting values but that is only for configuring the components i.e. beans.

Spring, XML beans call Annotation beans when app start

I have one Annotation bean with some methods. It works fine.
public #Controller("adminController") class AdminController {
...
private #Autowired AdminDAO adminDAO;
public void resetTemporalList() {
System.out.println("HE SIDO EJECUTADO.");
this.adminDAO.resetTemporalRegisters();
}
...
}
Now, I am integrating one quartz task. But I am load it with XML definition beans that call previus annotation bean.
<bean id="resetTemporalRegisters" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="adminController" />
<property name="targetMethod" value="resetTemporalList" />
<property name="concurrent" value="false" />
</bean>
Whan I start my app appear next error.
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'adminController' is defined
I believe the problem is that Spring load XML beans first, after Annotation beans, then in this moment "adminController" bean not exits...
How Can I fix it?
SOLVED IT!!
Problem was in I put xml bean definitions in applicationContext.xml.
No, XML and annotations integrate fine, but do you actually have the component scanning code in your XML?
<context:component-scan base-package="com.yourcompany.yourapp"/>
See: 4.10 Classpath scanning and managed components
A little bit of guessing: your controller is defined in child application context created by Spring MVC while you resetTemporalRegisters job in main application context (parent). Child context can access beans from parent context but not the other way around.
This raises important question: why is your business logic trying to call a method of a controller? These methods should be called only be the MVC framework. Can't you just call
this.adminDAO.resetTemporalRegisters();
directly from your job?
<bean id="resetTemporalRegisters" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="adminDAO" />
<property name="targetMethod" value="resetTemporalRegisters" />
<property name="concurrent" value="false" />
</bean>
adminDAO is probably defined in parent context, so you can access it easily.

Why is autowiring required? What is the explanation of the concept of autowiring?

Why is autowiring required? What is the explanation for the concept of autowiring?
#autowired annotation in Spring Framework.
Autowiring is not required, just convenient.
It means that if you have a property that requires an InterfaceA and a single bean has been declared in Spring that is of type InterfaceA, instead of using XML to manually "wire up" the relationship (setting a bean reference as a property of another), you can let Spring do the wiring for you.
This is a common question for the beginners. As the beans are injected using DI (setter injections, constructor injections), why do we need auto-wiring? Auto-wiring also doing the same thing, right?
The answer is, it saves you from writing more code.
If using an XML file, using autowire attribute saves you from writing the wiring code in the bean definition.
Please look at code below.
Configuration code without Auto-wiring:
<bean id="employee" class="com.Employee">
<property name="name" value="Dexter"></property>
</bean>
<bean id="employeeService" class="com.EmployeeService">
<property name="employee" ref="employee"></property>
</bean>
Configuration code with Auto-wiring:
<bean id="employee" class="com.Employee">
<property name="name" value="Dexter"></property>
</bean>
<bean id="employeeService" class="com.EmployeeService" autowire="byName" />
Note that we did not have to write anything to refer property of EmployeeService, i.e., Employee. But still it was injected. Autowiring makes the container to search the bean configurations and do the collaboration among beans, without the developer specifically mentioning these.
If we use annotation, even we don’t have to write anything in XML files, including this autoware="byName", etc. Simply #Autowired on bean's setter/field/constructor is sufficient.

Resources