I have two spring profiles: development and production.
There should be a common properties file (placed in classpath:properties/common/*.properties) which will be overridden by the profile's properties file (placed in classpath:properties/development/*.properties.
This is my context config snippet to clarify my intention:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.example.entities.*" />
<property name="hibernateProperties" ref="hibernateProperties" />
</bean>
<beans profile="development">
<context:property-placeholder location="classpath:properties/development/jdbc.properties" />
<bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="ignoreResourceNotFound" value="true" />
<property name="location" value="classpath:properties/development/hibernate.properties" />
</bean>
</beans>
<beans profile="production">
<context:property-placeholder location="classpath:properties/production/jdbc.properties" />
<bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="ignoreResourceNotFound" value="true" />
<property name="location" value="classpath:properties/production/hibernate.properties" />
</bean>
</beans>
Currently there's no common properties somewhere. How to merge a common properties file with the one in each profile for both jdbc.properties and hibernate.properties?
I've used JavaConfig for this:
#Configuration
#Profile("development")
public class DevelopmentConfig {
public #Bean String profile() {
return "development";
}
}
#Configuration
#Profile("production")
public class ProductionConfig {
public #Bean String profile() {
return "production";
}
}
public class PropertyUtils {
public static Properties getProperties(String profile, String filename) throws IOException {
Properties ret = new Properties();
ClassPathResource resource;
resource = new ClassPathResource("properties/common/" + filename + ".properties");
ret.putAll(PropertiesLoaderUtils.loadProperties(resource));
resource = new ClassPathResource("properties/" + profile + "/" + filename + ".properties");
if (resource.exists()) {
ret.putAll(PropertiesLoaderUtils.loadProperties(resource));
}
return ret;
}
}
#Configuration
public class MainConfig {
private #Autowired String profile;
// Here you can use: PropertyUtils.getProperties(profile, "jdbc"))
}
This should get you started
<bean id="allProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true"/>
<property name="ignoreResourceNotFound" value="true"/>
<property name="locations">
<list>
<value>classpath*:default.properties</value>
<value>classpath*:overrides.properties</value>
<value>file:${APP_HOME}/**/*.properties</value>
</list>
</property>
</bean>
Related
I am using apache commons httpclient 4.3.x along with spring3. I am trying to wire up a connectionpool with it's associated socketconfig instance.
http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.html
http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/config/SocketConfig.html?is-external=true
My code looks like this:
<bean id="socketConfig" class="org.apache.http.config.SocketConfig" factory-method="custom" init-method="build">
<property name="soTimeout" value="60000"/>
<property name="soLinger" value="5" />
</bean>
<bean name="poolingHttpConnectionManager" class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager" depends-on="socketConfig">
<property name="maxTotal" value="20" />
<property name="defaultMaxPerRoute" value="20" />
<property name="defaultSocketConfig" ref="socketConfig" />
</bean>
However, this is not working. The instance type that is used to setDefaultSocketConfig() on PoolingHttpClientConnectionManager is of type SocketConfig.Builder instead of SocketConfig.
What I want to have happen is as follows:
SocketConfig config = SocketConfig.custom()
.setSoTimeout(60000)
.setSoLinger(5)
.build()
So, I expect that the socketConfig bean type should be a SocketConfig instance, not a SocketConfig.Builder instance.
As per spring docs, I thought this should work.
http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#beans-factory-class-static-factory-method
is there anything I am doing wrong? Or is this just not supported in spring?
It turns out that the socketconfig builder instance is not designed to work with spring very well.
I had to use a spring beanfactory implementation to create the instance.
The bean class:
import org.apache.http.config.SocketConfig;
import org.springframework.beans.factory.FactoryBean;
public class SocketConfigFactoryBean implements FactoryBean<SocketConfig> {
int soLinger;
int soTimeout;
public SocketConfig getObject() throws Exception {
return SocketConfig.custom()
.setSoLinger(soLinger)
.setSoTimeout(soTimeout)
.build();
}
public Class<?> getObjectType() {
return SocketConfig.class;
}
public boolean isSingleton() {
return true;
}
public int getSoLinger() {
return soLinger;
}
public void setSoLinger(int soLinger) {
this.soLinger = soLinger;
}
public int getSoTimeout() {
return soTimeout;
}
public void setSoTimeout(int soTimeout) {
this.soTimeout = soTimeout;
}
}
The bean definition
<bean name="poolingHttpConnectionManager" class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager">
<property name="maxTotal" value="20" />
<property name="defaultMaxPerRoute" value="20" />
<property name="defaultSocketConfig">
<bean class="org.apache.http.config.SocketConfig" factory-method="custom" init-method="build">
<bean class="com.ex.spring.beans.factory.SocketConfigFactoryBean">
<property name="soTimeout" value="60000"/>
<property name="soLinger" value="5" />
</bean>
</property>
</bean>
I was able to achieve it by doing the next configuration in spring:
<bean id="socketConfig" class="org.apache.http.config.SocketConfig" factory-method="custom">
<property name="soTimeout" value="1000" />
<property name="soLinger" value="5" />
</bean>
<bean name="poolingHttpConnectionManager" class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager">
<property name="maxTotal" value="20" />
<property name="defaultMaxPerRoute" value="20" />
<property name="defaultSocketConfig">
<bean factory-bean="socketConfig" factory-method="build" />
</property>
</bean>
I upgraded to Spring 3.1.2, Neo4J 1.8.RC1 and SpringData 2.1.0.RC3 and I run into the following issue.
Before explaining the problem, here is part of my application context:
<!-- Neo4J -->
<neo4j:config storeDirectory="target/graph.db" entityManagerFactory="entityManagerFactory"/>
<neo4j:repositories base-package="***.repository"/>
<!-- H2 -->
<jdbc:embedded-database type="H2" id="accountDataSource">
<jdbc:script location="classpath:scripts/schema.sql" separator=";"/>
</jdbc:embedded-database>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="accountDataSource" />
<property name="packagesToScan" value="***.domain" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="showSql" value="false" />
<property name="databasePlatform" value="${database.dialect}" />
</bean>
</property>
</bean>
<!-- transactions -->
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven mode="aspectj" />
I run a very basic test :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:devinlove-core.xml")
#Transactional
public class MascotRepositoryTest {
#Autowired
private MascotRepository mascotRepository;
private Mascot mascot;
#Before
public void setup() {
mascot = new Mascot();
mascot.setName("Tux");
}
#Test
public void when_inserting_then_retrievable() {
assertThat(mascotRepository).isNotNull();
mascotRepository.save(mascot);
assertThat(mascot.getId()).isGreaterThan(0L);
}
}
And the test fails with a NPE. Why isn't mascot ID still null after the save operation?
MascotRepository is defined as follows:
public interface MascotRepository extends GraphRepository<Mascot> {}
Mascot itself is a very basic NodeEntity:
#NodeEntity
#TypeAlias("mascot")
public class Mascot {
#GraphId
private Long id;
#Indexed(indexType= FULLTEXT, indexName = "mascotSearch")
private String name;
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
#Override
public String toString() {
return "Mascot{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
I don't know if this can be relevant to the issue, but one of my NodeEntity is partial and therefore is modified by AspectJ (to add basic ActiveRecord methods). Can you confirm only partial NodeEntities are modified this way and not pure Neo4J entities? If not, can it cause conflict with repositories?
If you have any ideas, thanks in advance!
Rolf
I think the right definition of the transactionManager bean is this:
<bean id="jpaTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="jtaTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="org.neo4j.kernel.impl.transaction.SpringTransactionManager">
<constructor-arg ref="graphDatabaseService" />
</bean>
</property>
<property name="userTransaction">
<bean class="org.neo4j.kernel.impl.transaction.UserTransactionImpl">
<constructor-arg ref="graphDatabaseService" />
</bean>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.data.neo4j.transaction.ChainedTransactionManager">
<constructor-arg>
<list>
<ref bean="jpaTransactionManager"/>
<ref bean="jtaTransactionManager"/>
</list>
</constructor-arg>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean id="configProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="placeholderPrefix" value="${" />
<property name="placeholderSuffix" value="}" />
<property name="locations">
<value>classpath:ddes/config.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${datasource}"/>
<property name="resourceRef" value="true"/>
</bean>
<context:load-time-weaver weaver-class="org.springframework.instrument.classloading.weblogic.WebLogicLoadTimeWeaver"/>
<bean id="PersistenceUnit" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="defaultDataSource" ref="dataSource"/>
<property name="class">
<!--LIST BEANS-->
<value>....</value>
</property>
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="databasePlatform" value="org.eclipse.persistence.platform.database.OraclePlatform"/>
<property name="generateDdl" value="true"/>
<property name="showSql" value="true"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="persistenceUnitManager" ref="PersistenceUnit"/>
<property name="persistenceUnitName" ref="Persistence-ejbPU"/>
<property name="persistenceProvider" ref="org.eclipse.persistence.jpa.PersistenceProvider"/>
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="entityManagerFactory"/>
</bean>
implement
#CallByReference
#Stateless(mappedName = "cliente")
public class ClienteDAOBean implements ClienteDAOLocal, ClienteDAORemote {
#PersistenceUnit(unitName = "Persistence-ejbPU")
private EntityManagerFactory emf;
public Clientes find(Integer codCliente) throws Exception {
Clientes cliente = null;
EntityManager em = emf.createEntityManager();
try {
javax.persistence.Query q = em.createNamedQuery("Clientes.findByCodCliente").setParameter("codCliente", codCliente);
cliente = (Clientes) q.getSingleResult();
} catch (Exception e) {
throw e;
} finally {
em.close();
return cliente;
}
}
}
Pero al iniciar la aplicaciĆ³n el log arroja este error:
No persistence unit named 'Persistence-ejbPU' is available in scope Persistence-ejbPU.jar
was previously using a persistence.xml file but needed the name of the datasource out dynamic
Simply replace ref with value. Use:
<property name="persistenceUnitName" value="Persistence-ejbPU" />
instead of:
<property name="persistenceUnitName" ref="Persistence-ejbPU"/>
If you are having still problem then I would implement my own LocalContainerEntityManagerFactoryBean class which extends from AbstractEntityManagerFactoryBean so you can override setPersistenceUnitName then see what is going on.
i need to use bean from spring application context not in a spring managed bean, so i do next: annotate bean with #Service annotation, so instance of bean created during spring loading.
<bean id="customRevisionListener" class="ru.csbi.registry.services.impl.envers.CustomRevisionListener" />
This instance is ApplicationContextAware, so application context is injected in this bean instance and i save it to static variable:
#Service
public class CustomRevisionListener implements EntityTrackingRevisionListener, ApplicationContextAware {
private static ApplicationContext applicationContext;
private ModelInformationService modelInformationService;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
CustomRevisionListener.applicationContext = applicationContext;
}
private ModelInformationService getModelInformationService() {
if (modelInformationService == null) {
modelInformationService = applicationContext.getBean(ModelInformationService.class);
}
// TransactionProxyFactoryBean
return modelInformationService;
}
After that another instance of CustomRevisionListener created in not spring context(hibernate envers context). Here i use static variable to receive spring applicationContext
after that i'm getting beans from application context:
private ModelInformationService getModelInformationService() {
if (modelInformationService == null) {
modelInformationService = applicationContext.getBean(ModelInformationService.class);
}
the problem is that this bean has all #Autowired properties injected correctly:
#Service
public class ModelInformationServiceImpl implements ModelInformationService {
#Autowired
private EntityChangeService entityChangeService; // injected correctly
#Autowired
private PropertyService propertyService; // injected correctly
#Autowired
private ru.csbi.registry.services.reflection.HibernateDomainService hibernateService; // injected correctly
, but they are simple instances of java classes not Proxies supporting #Transactional annotation, which they are for my regular spring code:
getModelInformationService().getClass().getName() is "ru.csbi.registry.services.impl.envers.ModelInformationServiceImpl"
and must be something like
$Proxy71
How to get transaction supporting proxies, which spring genereates for example when injecting beans in #Controller, in bean not managed by spring?
i'm using next spring config:
<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg ref="lazyConnectionDataSourceProxy"/>
</bean>
<bean id="lazyConnectionDataSourceProxy" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource">
<ref local="dataSourceTarget" />
</property>
</bean>
<bean id="dataSourceTarget" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${ds.driver}" />
<property name="url" value="${ds.url}" />
<property name="username" value="${ds.user}" />
<property name="password" value="${ds.password}" />
<property name="initialSize" value="${ds.initialSize}" />
<property name="maxActive" value="${ds.maxActive}" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<!--property name="entityInterceptor">
<bean class="ru.csbi.registry.utils.audit.AuditLogInterceptor">
<property name="sessionFactory" ref="auditSessionFactory" />
</bean>
</property-->
<property name="dataSource" ref="dataSource" />
<property name="lobHandler" ref="oracleLobHandler" />
<property name="packagesToScan" value="ru.csbi.registry.domain" />
<property name="hibernateProperties">
<bean id="hibernatePropertiesFactoryBean" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>file:${realtyregistry.settings.path}/hibernate-config.properties</value>
</list>
</property>
</bean>
</property>
<property name="eventListeners">
<map>
<entry key="post-insert" value-ref="auditEventListener" />
<entry key="post-update" value-ref="auditEventListener" />
<entry key="post-delete" value-ref="auditEventListener" />
<entry key="pre-collection-update" value-ref="auditEventListener" />
<entry key="pre-collection-remove" value-ref="auditEventListener" />
<entry key="post-collection-recreate" value-ref="auditEventListener" />
</map>
</property>
</bean>
<bean id="auditEventListener" class="org.hibernate.envers.event.AuditEventListener" />
<bean id="persistenceManagerHibernate" class="ru.csbi.registry.utils.PersistenceManagerHibernate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
I am trying to implement Spring MVC 3 +EclipseLink JPA 2
When I call saveUser for example it returns that
NullPointerException, EntityManager is
null
:
public class UserDAO {
#PersistenceContext
private EntityManager em;
public void setEntityManager(EntityManager em) {
this.em = em;
}
#Transactional
public User saveUser(User user){
return em.merge(user);
}
My config is:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="application" />
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.eclipse.persistence.platform.database.MySQLPlatform" />
<property name="generateDdl" value="false" />
</bean>
</property>
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" />
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="username" value=".." />
<property name="password" value=".." />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://..." />
</bean>
Also have
<context:component-scan base-package="com.elasticbeanstalk.mypackage" />
<context:annotation-config />
It does initialize JPA during Tomcat startup. Why am I see NPE? Could I miss something?
If you instantiate the UserDAO manually, nothing will be injected by Spring. If the DAO is in a package which is under your base-package of <context:component-scan ../> then you can simply autowire it into your Controller. If not, either modify the base-package or also you can define the DAO in the appcontext manually, then you can autowire as well.