Spring Cloud Config Server without Spring Boot - spring

I have looked at spring-cloud-config client without Spring Boot and many others and have not found a convincing answer. So here it goes again:
Question:
Is it possible, in a Spring app, to use Spring Cloud Config server/client without the automagic configuration of Spring Boot? Is using Spring Boot a requirement for using these frameworks?
If it is:
Is there any documentation that clearly describes what needs to be done in order to enable Spring Cloud Config server/client without Spring Boot?
Is there any sample project that clearly describes what needs to be done in order to enable Spring Cloud Config server/client without Spring Boot??

I'm not aware of documentation or a sample project. However we are doing it in our projects.
You just need to include the configuration server URI as a property source, assuming you are using PropertySourcesPlaceholderConfigurer:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer" id="propertyPlaceholder">
<property name="locations">
<list>
<value>http://your-config-server.com:8888/application-${spring.profiles.active}.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="false"/>
</bean>
You have to make sure to pass -Dspring.profiles.active=current_profile to the java command line, like you probably would have done with boot.

Related

Disable integration flow - Spring integration

I need to implement a spring integration flow for error queues handling. The flow needs to be activated based on configuration property as the error queues are not setup for lower environments like DEV.
How can I activate/enable integration flow based on spring configuration property?
my integration flow looks like this:
<bean id="error.jms" class="com.xxx.backend.integration.jms.MyMessageListener">
<property name="destinationName" value="#{queueConfig.getError().queueName()}"/>
<property name="errorHandler" ref="ErrorHandler"/>
</bean>
<intjms:message-driven-channel-adapter id="errorAdapter"
container="error.jms"
auto-startup="${xxx.backend.jmsAdaptor.autoStart}"
role="systemEndpoint"
channel="error.channel"/>
It sounds more like you need to make yourself familiar with Spring's Bean Definition Profiles.
So, what you would need is something like this for your config:
<beans profile="production">
<bean id="error.jms" class="com.xxx.backend.integration.jms.MyMessageListener">
...
</bean>
<intjms:message-driven-channel-adapter id="errorAdapter"
...
channel="error.channel"/>
</beans>
Then you just need to activate it when you start the app in the production., e.g. -Dspring.profiles.active=production.

MongoDB Batch Job Broken in Spring XD 1.2.0+

We have a batch job running in Spring XD which reads from MongoDB using the standard MongoItemReader which converts mongo records to our domain model. Up to Spring XD version 1.1.3 this worked fine, however in versions 1.2.0 and 1.2.1 the job is failing with the following error (package name shortened)
java.lang.NoClassDefFoundError: c/s/r/b/b/domain/IndexId
at c.s.r.b.b.domain.IndexId_Instantiator_hxmj4p.newInstance(Unknown Source) ~[na:na]
at
org.springframework.data.convert.BytecodeGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(BytecodeGeneratingEntityInstantiator.java:193) ~
[spring-data-commons-1.10.0.RELEASE.jar:na]
at org.springframework.data.convert.BytecodeGeneratingEntityInstantiator.createInstance
(BytecodeGeneratingEntityInstantiator.java:76) ~[spring-data-commons-1.10.0.RELEASE.jar:na]
at
org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:250) ~[spring-data-mongodb-1.7.0.RELEASE.jar:na]
at
org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:231) ~[spring-data-mongodb-1.7.0.RELEASE.jar:na]
Looking into this I found the threads NoClassDefFoundError when making a query in spring-data-solr within a play framework application, and NoClassDefFoundError after upgrading to 1.7.0.RELEASE which suggest this is due to a change in spring-data-mongo 1.7.0 and the underlying spring-data-commons to change the default entity instantiation technique to improve performance.
Based on the suggested fix in those threads I've modified the mongo template in my job module XML definition as follows and this fixes the problem:
<bean id="mappingConverter" class="org.springframework.data.mongodb.core.convert.MappingMongoConverter">
<constructor-arg ref="dbRefResolver"/>
<constructor-arg ref="mongoMappingContext"/>
<property name="instantiators" ref="entityInstantiators" />
</bean>
<bean id="dbRefResolver" class="org.springframework.data.mongodb.core.convert.DefaultDbRefResolver">
<constructor-arg ref="mongoDbFactory"/>
</bean>
<bean id="mongoMappingContext" class="org.springframework.data.mongodb.core.mapping.MongoMappingContext"/>
<bean id="entityInstantiators" class="org.springframework.data.convert.EntityInstantiators">
<constructor-arg value="#{T(org.springframework.data.convert.ReflectionEntityInstantiator).INSTANCE}"/>
</bean>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<constructor-arg name="mongoConverter" ref="mappingConverter" />
</bean>
However this is verbose and obviously isn't an ideal fix. The problem doesn't show up in our job module integration test so I have a hunch its caused by a combination of the default entity instantiation change and the fact that when a module executes in Spring XD the domain classes will be in the module's class loader and not visible to the spring data mongo classes in XD's main class loader.
So should this be regarded as a bug in Spring XD or Spring Data Mongo? One fix might be an improvement to the Spring Data Mongo mongo:mapping-converter XML configuration to allow forcing the use of the ReflectionEntityInstantiator which would at least reduce the amount of XML needed above. Alternatively maybe Spring XD should handle this scenario automatically?
I don't think there is anything we can do from the XD side since this is a custom job. We have to rely on the spring-data-mongodb functionality.
It looks like you're running into DATACMNS-710, which is fixed in Fowler SR1 (equivalent to Spring Data MongoDB 1.7.1). You might wanna try the just released Gosling release, too.

Using Spring Transactions in MyBatis API

We have developed a data persistence framework using Mybatis. The framework uses plain MyBatis APIs. (We were prohibited from using any mybatis-spring, do not ask… why?)
Now we have to integrate this persistence framework with another framework developed by other teams. This other framework heavily uses spring transactions for everything. Our persistent framework DAOs will be used by this framework within its own API ….that means the spring managed transactions will be propagated to MyBatis DAO. It is expected that our MyBatis based persistence framework should participate in spring managed transactions without any issues.
There are two options for us to make this work
(1)Change our persistent framework to use mybatis-spring module. Change DAOs to use mappers directly injected using spring and spring’s SqlSessionFactoryBean. I did build a small example simulating both the frameworks and everything works without any issue. The problem is with this approach that it requires changing almost all the DAOs to use spring injected mapper, extensively test the framework again. We simply do not have time available due to delivery timeline.
(2)Use mybatis-spring, define SqlSeeionFactory using spring – set the datasource and transaction manager used by other framework. Something like
<bean id="smpDataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close">
<property name="connectionCachingEnabled" value="true" />
<property name="URL"> <value>${db.thin.url}</value></property>
<property name="user"> <value>${db.user}</value></property>
<property name="password"><value>${db.password}</value>
</property>
</bean>
<bean id="dbTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="smpDataSource" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="smpDataSource" />
<property name="typeAliasesPackage" value="spike.smp51.domain" />
<property name="mapperLocations" value="classpath*:spike/smp51/mappers/*.xml" </bean>
Then in applicataion code MyBatis DAO gets the sqlseesionfactory from spring like
public static SqlSessionFactory getSqlSessionFactory() throws Exception
{
DefaultSqlSessionFactory sessionFactory = (DefaultSqlSessionFactory)ctx.getBean("sqlSessionFactory");
return sessionFactory;
}
All DAOs already use SqlSeesionFactory to open and close sessions. Just replace that mybatis created sqlseeionfactory with spring created sqlseeionfactory. That way we will have only few lines of changes.
This approach is outlined here
http://mybatis.github.io/spring/using-api.html
The mybatis documentation warns about this approach – specifically that it will not participate in spring transactions.
When I tried the 2nd approach, our framework was able to participate in spring transactions. This is strange. Is the MyBatis documentation incorrect then? I did verify it extensively by creating various transaction boundaries using spring transactions + AOP . MyBatis DAOs are able to participate in spring managed transactions every time. Since this second approach will save us 90% of the development time – we really like to use it – but worried since MyBatis warns following this approach. Has anyone tried this approach? Any feedback is greatly appreciated.
Did you have any return on that ?
I'm wondering if in the doc they're talking about org.apache.ibatis.session.SqlSessionFactory from Mybatis-api while the SqlSessionFactory you're using is from the mybatis-spring lib : org.mybatis.spring.SqlSessionFactoryBean

Spring does not autowire beans with JAX-WS webservice end points

I am trying to consume a JAX-WS webservice written by me. I always get nullPointerException for spring autowired annotated beans. However, everything works fine within serverSide over web, but accessing beans through JAX-WS webservice.
I have tried by extending SpringBeanAutowiringSupport, but still no luck. How can I do this.
regards, Rohit
I had no experience extending SpringBeanAutowiringSupport but had successfuly used this approach:
Annotate webService class such a way :
#Component("yourWebService")
#WebService(endpointInterface ="your.package.YourServicePort")
Create new spring-context xml for webService and define JAX-WS endpoint :
<jaxws:endpoint
id="yourServiceEndpoint"
implementor="#yourWebService"
address="${yourWebService.wsdl.url}"> //load url from properties file
</jaxws:endpoint>
I suppose you know how to use props in spring, but will explain just in case. You should also create yourWebService.properties file and define it in spring context to use this construction ${yourWebService.wsdl.url} :
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>yourWebService.properties</value>
</list>
</property>
Using this approach I had successfuly used JAX with Spring

How to perform anonymous authentication?

I always thought that acegi security is the same as spring security 3.0... but It seems to be wrong.
Unfortunately I was unable to find any acegi security docs.
I need to have an anonymous user with special role assigned into Security Context what I found about that was this.
But there's no AnonymousAuthenticationFilter in ACEGI - only AnonymousProcessingFilter. But how should I call it's id?
I tried this code:
<bean id="anonymousAuthFilter"
class="net.sf.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="key" value="foobar"/>
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</bean>
<bean id="anonymousAuthenticationProvider"
class="net.sf.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
<property name="key" value="foobar"/>
</bean>
But I get nothing in my Security Context before I actually login. And that's bad=(
Any ideas?
acegi security is the old name of spring security. (in 2.0 or older I can't remember, it is to long ago)
I strongly recommend to use Spring Security 3.0. Attention: The Package Names and Jar Structure was Changed between Spring Security 3.0 und Spring Security 2.0.
So if you have current documentation you will need to translate it back to 2.0. This Blog Spring Security 3.0.0.M1 Released describe the changes.

Resources