Inject SessionFactory from Spring XML-Config into Java-Config - java

For some reason i have my spring beans config as java config and also some other beans are defined in xml.
Now i want to inject the sessionfactory bean defined in xml config into a bean in java config.
Unfortunately sessionfactory is null and i get a NullPointerException.
What's wrong? I'm using Spring 3.2.5. Also #Inject or #Autowired instead of #Resource doesn't work.
Here are the relevant parts...
Java Config:
#Configuration
#ComponentScan
#ImportResource({ "classpath:beans-sessionfactory.xml" })
public class MyJavaConfig {
// defined in 'beans-sessionfactory.xml'
#Resource
//#Inject => also NPE
//#Autowired => also NPE
private AnnotationSessionFactoryBean sessionFactory;
#Bean
public MyDao getMyDao() {
final MyDao dao = new MyDao();
// Why is sessionFactory null?
dao.setSessionFactory(this.sessionFactory.getObject());
return dao;
}
// MyAppConfig extends PropertyPlaceholderConfigurer
#Bean
public MyAppConfig myAppConfig() {...}
...
XML-Config:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
...
</bean
Unit-Test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { MyJavaConfig.class })
public class MyBeanWiringTest {
// test fails with NPE
}
The almost complete beans-sessionfactory.xml:
<?xml version="1.0" encoding="ISO-8859-15"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" lazy-init="true">...</bean>
<bean id="myProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">...</bean>
<bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">...</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="hibernateProperties" ref="hibernateProperties"/>
<property name="annotatedClasses">
<list>
<value>MyEntity</value>
</list>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
</beans>

The AnnotationSessionFactoryBean is a FactoryBean<SessionFactory> which means that it creates a SessionFactory. You can inject the result instead of the factory.
#Configuration
#ComponentScan
#ImportResource({ "classpath:beans-sessionfactory.xml" })
public class MyJavaConfig {
#Autowired
private SessionFactory sessionFactory;
#Bean
public MyDao getMyDao() {
final MyDao dao = new MyDao();
// Why is sessionFactory null?
dao.setSessionFactory(this.sessionFactory);
return dao;
}
If you really want the AnnotationSessionFactoryBean you will have to resort to some naming trickery. You have to inject a bean with the name '&sessionFactory' notice the & this is the marker to indicate to spring that you want to FactoryBean instead of the result of the FactoryBean.
#Autowired
#Qualifier("&sessionFactory")
private AnnotationSessionFactoryBean sessionFactory;

The problem is here:
Bean method MyJavaConfig.myAppConfig is non-static and returns an
object assignable to Spring's BeanFactoryPostProcessor interface.
This will result in a failure to process annotations such as
#Autowired, #Resource and #PostConstruct within the method's declaring
#Configuration class. Add the 'static' modifier to this method to
avoid these container lifecycle issues; see #Bean Javadoc for complete
details
So after declaring myAppConfig static it works.
#Bean
public static MyAppConfig myAppConfig() {...}

Related

How can I add my custom type converters to SpringBoot

Config my custom type converters by using (Spring 4.x)XML properties like this.
<mvc:annotation-driven conversion-service="factoryBean" />
<bean class="org.springframework.context.support.ConversionServiceFactoryBean" id="factoryBean" >
<property name="converters">
<list>
<bean class="com.mvc.convertor.MyConvertor" />
</list>
</property>
</bean>
MyConvertor implements org.springframework.core.convert.converter.Converter.
And how can I config my custom type converters by using SpringBoot.I have tried many methods but failed.Hope any one can help me to resolve.Thanks!
As Stephane Nicoll pointed out spring boot should automatically pick up any converters registered as bean configuration in your application.
#Configuration
#EnableWebMvc
public class MyConfiguration {
#Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = ...
HttpMessageConverter<?> another = ...
return new HttpMessageConverters(additional, another);
}
}

JMock class mocks in Spring Context

I'd like to inject JMock mock beans from Spring XML Configuration.
I have the following test
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "/application-context-test.xml")
public class CorporateInfoServiceImplTest
{
#Autowired
private Mockery mockery;
#Autowired
private CorporateInfoServiceImpl corporateInfoService;
#Test
public void createCorporateInfo() {...}
}
And such XML configuration:
<bean id="mockery" class="org.jmock.Mockery">
<property name="imposteriser">
<util:constant static-field="org.jmock.lib.legacy.ClassImposteriser.INSTANCE"/>
</property>
</bean>
<bean id="createCorporateInfoOperation" class="com.acme.corp.ws.operation.CreateCorporateInfoOperation" factory-bean="mockery" factory-method="mock">
<constructor-arg value="com.acme.corp.ws.operation.CreateCorporateInfoOperation" type="java.lang.Class" />
</bean>
<bean id="corporateInfoService" class="com.acme.corp.ws.CorporateInfoServiceImpl">
<property name="createCorporateInfoOperation" ref="createCorporateInfoOperation" />
</bean>
CorporateInfoServiceImpl and CreateCorporateInfoOperation are kind of:
public class CorporateInfoServiceImpl implements CorporateServiceInterface
{
#Autowired
CreateCorporateInfoOperation createCorporateInfoOperation;
...
}
#Component
public class CreateCorporateInfoOperation
{
#Autowired
CorporateInfoDao corporateInfoDao;
...
}
When trying to autowire the CorporateInfoServiceImpl I get the following exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.acme.corp.dao.CorporateInfoDao] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
The problem is that CreateCorporateInfoOperation tries to autowire dao even when created form factory-method. How can I disable such autowiring?
Other variants of injecting mock beans in JMock are appreciated.
Thanks in advance

how to run test in spring mvc

I'm trying to run some tests for my controller but somehow the #Autowire annotation is not working.
Here is what I'm trying to do:
#WebAppConfiguration
#ContextConfiguration("/WEB-INF/spring/app-config.xml")
public class ClientsTest {
private Client client = new Cliente();
#Test
public void test() {
BindingResult result = mock(BindingResult.class);
ClientController clientController = new ClientController();
ModelAndView model = clientController.regClient(client, result);
Assert.assertEquals("success", model.getViewName());
}
}
#Controller
public class ClientController {
#Autowired private ClientService clientService;
#RequestMapping(value="/regClient.html", method = RequestMethod.POST)
public ModelAndView regClient(#ModelAttribute("client") #Valid Client client, BindingResult result){
ModelAndView model = new ModelAndView();
if(result.hasErrors())
{
model.setViewName("error");
}
else
{
model = clientService.regClient(client);
model.setViewName("success");
}
return model;
}
}
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package="com.app.app_v2.web" />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>client</value>
</list>
</property>
</bean>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<ref bean="clientFormatter"/>
</set>
</property>
</bean>
<bean id="clientFormatter" class="com.app.app_v2.spring.ClientFormatter"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean id="clientService" class="com.app.app_v2.services.ClientService"/>
</beans>
As far as I know the clientService is null and this is why I'm getting the exception.
Because I don't know much about running test I'm asking for your help.
Your immediate problem about #Autowire not working is related to the fact that you're explicitly instantiating the clientController, and not through Spring framework. If you want the class to be a Spring bean you need to let the Spring framework manage its lifecycle, only than the dependency injection will kick-in, and all the spring beans annotated with #Autowire will be injected. Moreover, the test should be run with spring runner SpringJUnit4ClassRunner
Note that this is not necessary, cause with your test you can go two ways. More towards unit testing, by mocking your clientService e.g. via EasyMock or Mockito. Your currently posted test looks more geared towards that way. To learn how to complete your test take a look at this blog post
On the other hand, you can go for an integration test. Since version 3.2 Spring MVC offers test module which should really be the way to write integration test against Spring MVC. You can follow a great blog series backed with source code to learn how to do it.

Spring property with util:property-path as annotation

<bean id="groupContainerRelationshipDAO" class="containermanager.management.dao.GroupContainerRelationshipDAOImpl">
<property name="dataSource">
<util:property-path path="dataSourceFactory.dataSource" />
</property>
</bean>
I would like to define this as spring annoations. The problem is dataSource is a memeber of the inherited class SimpleJdbcDaoSupport. Does someone knows how to do this?
This one:
#Component
class GroupContainerRelationshipDAOImpl {
#Value("#{dataSourceFactory.dataSource}")
private DataSource dataSource;
}
Read more about #Value annotation: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-annotation-config

How to use SimpleJdbcDaoImpl accross different classes - Spring

I'm getting a null pointer when I try to access and use a SimpleJdbcDaoSupport. This is how I'm working it out:
In the main class
#Override
public void start(final Stage primaryStage) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
SimpleJdbcDaoImpl dao = ctx.getBean("simpleJdbcDaoImpl", SimpleJdbcDaoImpl.class);
In some other stage controller class
public class HomeController implements Initializable {
#Autowired
private SimpleJdbcDaoImpl simpleJdbcDaoImpl;
// Initializes the controller class.
#Override
public void initialize(URL url, ResourceBundle rb) {
// Stage and the rest called
}
#FXML
public void showNewCalendarStage() throws Exception {
System.out.println(simpleJdbcDaoImpl.getCircleCount());
}
The SimpleJdbcDaoSupport class
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
public class SimpleJdbcDaoImpl extends SimpleJdbcDaoSupport {
public int getCircleCount() {
String sql = "SELECT COUNT(*) FROM KIWI_TABLE";
return this.getJdbcTemplate().queryForInt(sql);
}
}
The spring.xml
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:file:C:/WAKILI/WAKILIdb"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="simpleJdbcDaoImpl" class="wakiliproject.dao.SimpleJdbcDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="configLocation">
<value>
classpath:/hibernate.cfg.xml
</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.H2Dialect</prop>
</props>
</property>
</bean>
<context:annotation-config/>
<context:component-scan base-package="wakiliproject"/>
</beans>
The error:
Caused by: java.lang.NullPointerException
at HomeController.showNewCalendarStage(HomeController.java:283)
... 42 more
I'm trying to teach myself Spring and would like to, for example, populate a Label in another Controller class (other than the main class) with text retrieved from the database.
For simplicity, in this case, lets print some text from the database to the console. What am I doing wrong with the above code? Thank you all.
In order for a Spring bean to be injected with its collaborators, it has to be managed by Spring. The HomeController is actually managed by FXML, which knows nothing about Spring annotations (#Autowired) and will ignore them. Even worse, assuming that the HomeController is under the wakiliproject package (or one of its subpackages), Spring will indeed create another instance of the HomeController that will have the #Autowired stuff injected but NOT the #FXML stuff.
Depending on how you load the controller you may be able to set the instance of the HomeController retrieved from Spring as the controller of the .fxml view. So:
Make sure Spring actually sees the HomeController (this will give you an instance of HomeController with the #Autowired stuff injected).
Load the FXML document as:
HomeController homeController = springContext.getBean(HomeController.class);
FXMLLoader fxmlLoader = new FXMLLoader(xxx.getResource("HomeController.fxml"));
fxmlLoader.setController(homeController);
try {
fxmlLoader.load();
} catch...
The above is almost pseudo-code, adapt as necessary!
If the load() is successful, the the #FXML fields of the controller will be populated too and its initialization method will be called.
Check out the VERY helpful answer to this question.

Categories

Resources