I'm new to Spring Data and to Spring in general, so don't be hard on me.
I can't find a way to instantiate a repository. I read the documentation:
http://docs.spring.io/spring-data/data-solr/docs/1.0.0.RC1/reference/htmlsingle/#repositories.create-instances
It describes different ways of declaring repositories (xml, filters, etc), but doesn't say how I can get an instance of it in my code.
Here is my configuration xml file:
<?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:solr="http://www.springframework.org/schema/data/solr"
xsi:schemaLocation="http://www.springframework.org/schema/data/solr http://www.springframework.org/schema/data/solr/spring-solr-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<solr:repositories base-package="spring" />
<solr:solr-server id="solrServer" url="http://localhost:8983/solr" />
<bean id="taskRepo" class="spring.SolrTaskRepository">
</bean>
<bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
<constructor-arg index="0" ref="solrServer"/>
</bean>
</beans>
And SolrTaskRepository:
public interface SolrTaskRepository<T, ID extends Serializable> extends SolrCrudRepository<T, ID> {
Page<T> findByOrigin(String origin, Pageable page);
}
Could someone help me out?
If you want to use the repo(or any spring bean) somewhere out of the context:
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
MyRepo obj = (MyRepo) context.getBean("myRepo");
If you use the repo in some other bean managed by spring(some service) you can autowire it
#Autowire
private MyRepo myRepo;// + setter
or inject it in the context:
<bean id="someService" class="com.org.core.SomeService">
<property name="myRepo" ref="myRepo" />
</bean>
For both ways you need the bean defined in the context:
<bean id="myRepo" class="com.org.core.MyRepo">
</bean>
Example context file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="myRepo" class="com.org.core.MyRepo">
</bean>
</beans>
IF you load the context with ClassPathXmlApplicationContext you need the file in the classpath.
Related
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"
default-autowire="byName">
<bean name="schedulerMap" class="java.util.HashMap">
<constructor-arg>
<map>
<entry key="moBiScheduler" value-ref="moBiScheduler"/>
<entry key="billJobScheduler" value-ref="billJobScheduler"/>
</map>
</constructor-arg>
</bean>
</beans>
That's some of the XML.
In the class, I want to use #Autowired to inject the value of key='moBiScheduler' and key='billJobScheduler'
#Autowired
private Map<String, Scheduler> schedulerMap;
It's possible , you can
autoriwre a method that takes Map and do some filtering and put the right values to schedulerMap
Create another class MapHolder which extends Map (it's optional) and implements ApplicationContextAware. after the injection of ApplicationContext you can retrieve schedulerMap and do some filtering and put the right value to your map , then inject this map
you can also use BeanPostProcessor
I'm facing the problem, that the annotation #Autowired doesn't work anymore (in all Java classes that uses this annotation) if I remove the component-scan tag from config
<?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">
<context:component-scan base-package="efco.auth" />
here are some beans...
There is only one class in the efco.auth package, and this one has no relation to the following class EfcoBasketLogic.
and a class that uses #Autowired:
package efco.logic;
public class EfcoBasketLogic extends BasketLogicImpl {
#Autowired
private EfcoErpService erpService;
This Bean is defined in an other spring config file:
<bean id="BasketLogic" class="efco.logic.EfcoBasketLogic">
<property name="documentLogic" ref="DocumentLogic" />
<property name="stateAccess" ref="StateAccess" />
<property name="contextAccess" ref="ContextAccess" />
</bean>
As you can see, erpService is not defined. The other three properties are on BasketLogicImpl and have setters.
What I'm doing wrong?
As Tomasz says, you need <context:annotation-config/> for #Autowired to work. When you had <context:component-scan/>, it implicitly included annotation-config for you.
Adding either autowire="byType" or autowire="byName" to your bean declaration should do the job.
I have been using spring transactional management in a project dealing with JUnit Testing. I have gotten this to work fine for my JUnit tests but I cannot get it to work outside of that. Here is my basic scenario:
I have a class which handles DbUnit Initialization similar to this:
#TransactionConfiguration( defaultRollback = true )
#Transactional(propagation=Propagation.REQUIRED)
public class DbUnitManagerImpl implements DbUnitManager {
#Override
public void initializeDatabase(String location) {
// Does work to create a dataset from the file at location
// Calls a function within this class to execute the dbUnit initialization
runSetUp()
}
public void runSetUp() {
// Executes dbUnit call to initialize database
}
}
I am using this class in two different instances. I use it when running JUnit tests to initialize data and I also call these functions from a Backing Bean for a webpage.
The JUnit setup will properly rollback and looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:/context/applicationContext-rdCore.xml" })
#TransactionConfiguration( defaultRollback = true )
#Transactional(propagation=Propagation.REQUIRED)
public abstract class BaseDatabaseTest {
#Autowired private DbUnitManager dbUnitManager;
#Test
public void runTest1() {
dbUnitManager.initializeDatabase("D:\\test.xml");
}
}
My backing bean works in a similar way however it allows the DbUnitManagerImpl to do all the transactions. I have debugged that transactions are being started using:
System.out.println(TransactionSynchronizationManager.isActualTransactionActive());
In both cases true is displayed showing that a transaction is being started however rollback only occurs for the JUnit test. The backing bean looks like this:
#Service
#SessionScoped
public class DbUnitInitializerBean {
#Autowired private DbUnitManager manager;
/**
* Initializes the database using the files at <code>location</code>
*/
public void initializeDatabase() {
manager.initializeDatabase("D:\\test.xml);
}
}
A few notes:
The three classes mentioned above are obviously stripped down. They also reside in three different java projects. The backing bean resides in a web project which has the following application context:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
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/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:annotation-config />
<cache:annotation-driven />
<context:component-scan base-package="com.nph.rd.dbunit" />
<import resource="classpath:/context/applicationContext-rdCore.xml"/>
</beans>
The application context for my test Project which houses the DbUnitManagerImpl class looks like:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
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/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:annotation-config />
<cache:annotation-driven />
<import resource="classpath:/context/applicationContext-rdCore.xml"/>
</beans>
The main application context resides in the project which houses my JUnit tests and looks like:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
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/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:annotation-config />
<tx:annotation-driven />
<context:component-scan base-package="com.nph.rd.dbunit" />
<context:component-scan base-package="com.nph.dbunit" />
<bean id="dbUnitManager" class="com.nph.dbunit.dao.impl.DbUnitManagerImpl">
</bean>
<!-- allows for ${} replacement in the spring xml configuration from the .properties file on the classpath -->
<context:property-placeholder location="classpath:/properties/core-system.properties" ignore-unresolvable="true"/>
<!-- Transaction Manager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- OLTP data source -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${oltp.database.driverClassName}" />
<property name="url" value="${oltp.database.url}" />
<property name="username" value="${oltp.database.username}" />
<property name="password" value="${oltp.database.password}" />
</bean>
</beans>
The basic end goal is I will have my DbUnitManager class able to rollback on an exception basis when using it from the Backing Bean but have it rollback no matter what when used from my JUnit tests. Currently I have the DbUnitManager class set up to always rollback simply because I am trying to get transaction rollback to work in general. After I get it working I will move it over to rolling back on an exception basis.
Remove the following from your DbUnitManagerImpl
#TransactionConfiguration( defaultRollback = true )
This annotation only goes with the Spring TestRunner. By default the Spring TestRunner will rollback all transactions, so you can override that behavior with the #TransactionConfiguration.
If you are using a Spring TransactionManager (which you are), it will automatically rollback on uncaught runtime exceptions. If you want to rollback for checked exceptions, you can specify them in the #Transactional annotation or convert them to runtime ones.
#Transactional(rollbackFor = SomeCheckedException.class)
public void someMethod() {}
I am writing a RESTful service (using CXF on JBoss) in which I have inject another class using Spring (Autowired). But the class is not getting injected and is null.
Web Service Interface and Class (Where injection needs to happen)
package com.company.project.web;
#Path("/myws")
public interface IMyWebService {
#POST
#Path("/doSomething")
#Consumes("application/json")
#Produces("application/json")
MyResponse doSomething(MyRequest myRequest)
}
#Service("myWebService")
public class MyWebService implements IMyWebService {
#Autowired
private IMyCore myCore;
public MyResponse doSomething(MyRequest myRequest) {
....
}
}
That which has to be injected
package com.company.project.biz;
public interface IMyCore {
MyResponse doSomething(MyRequest myRequest);
}
#Component("myCore")
public class MyCore implements IMyCore {
public MyResponse doSomething(MyRequest myRequest) {
.....
}
}
Beans.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:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
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://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-http.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<context:annotation-config />
<context:component-scan base-package="com.company.project"/>
<jaxrs:server id="myWebService" address="/">
<jaxrs:serviceBeans>
<bean class="com.company.project.web.MyWebService" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="json" value="application/json" />
</jaxrs:extensionMappings>
</jaxrs:server>
</beans>
My service is active (http://localhost:8080/{warname}/myws/doSomething) but the MyCore instance is not being injected into MyWebService (in the myCore field). It is always null and my service does not work as expected, instead throws NullPointerException
Tried all inputs gathered over google. No luck! Your help is highly appreciated.
Regards
Try to add below method to your web service:
#PostConstruct
public void init() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
The current web application context (usually the one loaded by ContextLoaderListener) will be used for autowiring, so the IMyCore bean has to be defined in the context listener configuration file and not in the web service one.
If you want to use Spring Beans in CXF Web Service class, then declare WebService as following in the XML configuration file of the CXF (e.g. spring-cxf.xml)
<bean id="hello" class="demo.spring.service.HelloWorldImpl" />
<jaxws:endpoint id="helloWorld" implementor="#hello" address="/HelloWorld" />
Declare separated bean for the WebService class and then put it in the endpoint with an ID. Like this you will have spring managed bean, where you can use AutoWired annotations as well.
Your beans never won't be injected automatically if you will declare your web service as following.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<jaxws:endpoint id="helloWorld" implementor="demo.spring.service.HelloWorldImpl" address="/HelloWorld"/>
In this case you will need either:
Inject spring beans manually
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
Or retrieve the beans one by one from the spring context
ApplicationContext context = ...; // your Spring ApplicationContext
HelloBean helloBean = (HelloBean) context.getBean("bean");
I haven't tried this for JAX-RS, but the approach in my opinion should be the same.
From CXF official documentation.
Try to add below bean configuration at Beans.xml
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
In my case, it worked..
I am using Unitils with Spring for unit testing. I've configured Spring with datasource using a properties file.
My question is how can I use the same datasource or the same properties for Unitils?
Unitils expects a file in the classpath unitils.properties with database configuration parameters like url, user, password and driver.
I've tried to configure Unitils using the properties used in the Spring configuration as below but it is not working.
database.driverClassName=${jdbc.driver.class}
Thanks,
Adi
One potential solution... You could have your Spring configuration read its datasource parameters from the unitils.properties, instead of the other way around. Probably not ideal.
I believe unitils is using spring under the covers, so you might also try adding your datasource context in your unitils tests by using #SpringApplicationContext. If you could figure out the name of the datasource bean setup by unitils when it starts up, you could override it in your context (assuming the unitils datasource bean is created before the other spring beans are which may/may not be true.)
e.g.
#SpringApplicationContext({"correctDataSourceContext.xml"})
EDIT: Another option that will definitely work: https://stackoverflow.com/a/6561782/411229
Basically instantiate Unitils yourself and set the properties manually.
Ryan answer is correct and helpful as well though I've used different approach.
I extended the class PropertiesDataSourceFactory ro override the methods as follows:
public class UnitilsDataSourceFactory extends PropertiesDataSourceFactory {
#Override
public void init(Properties configuration) {
try {
String[] configFiles = new String[] { "applicationContext-test.xml" };
BeanFactory factory = new ClassPathXmlApplicationContext(configFiles);
SystemPropertiesReader systemPropertiesReader = (SystemPropertiesReader) factory.getBean("systemPropertiesReader");
Properties loadProperties = systemPropertiesReader.loadProperties();
super.init(loadProperties);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public DataSource createDataSource() {
DataSource dataSource = super.createDataSource();
return dataSource;
}
}
and also wrote a SystemPropertiesReader as:
public class SystemPropertiesReader {
private Collection<Resource> resources;
public void setResources(final Collection<Resource> resources) {
this.resources = resources;
}
public void setResource(final Resource resource) {
resources = Collections.singleton(resource);
}
#PostConstruct
public Properties loadProperties() throws Exception {
final Properties systemProperties = System.getProperties();
for (final Resource resource : resources) {
final InputStream inputStream = resource.getInputStream();
try {
systemProperties.load(inputStream);
} finally {
//
}
}
return systemProperties;
}
}
and added a bean with the properties file:
<bean id="systemPropertiesReader" class="uk.co.friendslife.eventmanager.domain.dao.SystemPropertiesReader">
<property name="resource">
<value>classpath:/META-INF/em/config/eventmanager_${database_name_lower}.properties</value>
</property>
</bean>
add the following to unitils.properties:
org.unitils.database.config.DataSourceFactory.implClassName=x.y.UnitilsDataSourceFactory
Just want to add some idea and im not sure if it is a best practice or not so correct me if theres something wrong.
MYPROJECT
-src
--TestPackage
---BaseServiceTest.class
---BlogspotServiceTest.class
--hibernate.cfg.xml
-web
--WEB-INF
---blogspot-servlet-test.xml
---jdbc-test.properties
in my case I used my blogspot-servlet-test.xml to call or to create the datasource
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
.... some bean configuration
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="file:web/WEB-INF/jdbc.properties"/>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- DAO'S -->
<bean id="blogspotDAO" class="package.BlogspotDAOImpl"/>
<!-- SERVICES -->
<bean id="blogspotService" class="package.BlogspotServiceImpl"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
MY jdbc-test.properties file
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQL5Dialect
jdbc.databaseurl=jdbc:mysql://127.0.0.1:3306/dbspringminiblogtest
jdbc.username=root
jdbc.password=
For hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd//hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mapping class="somePackage.entity.Author"/>
<!-- Other Entity Class to be mapped -->
</session-factory>
</hibernate-configuration>
and i created BaseClass for me to lessen creating of multiple #SpringApplicationContext annotation and it is also use to configure common configuration needed in testing other class, just extends it.
#SpringApplicationContext({"file:web/WEB-INF/blogspot-servlet-test.xml"})
public class BaseServiceTest extends UnitilsJUnit4 {
}
i used #SpringApplicationContext to load the datasource and other bean configurations on my BaseClass and this is how i implement it.
Below : see Spring-Unitils Tutorial
for more details
public class BlogspotServiceTest extends BaseServiceTest{
#Mock
#InjectInto(property = "blogspotDAO")
#SpringBean("blogspotDAO")
private BlogspotDAO blogspotDAOMock;
#TestedObject
#SpringBean("blogspotService")
private BlogspotService blogspotServiceMock;
#Test
public void testAddBlogSpot() {
assertNotNull("BlogspotService Not null",blogspotServiceMock);
}
}
NOTE: please create unitils.properties and unitils-local.properties inside TestPackage to be able to run the program.
For #SpringBean explanation and other annotation please read :
Unitils-EasyMock