spring-boot cloud stream with Kafka as a stand alone library - spring-boot

I'm trying to integrate a library based on spring-boot cloud stream with Kafka within non-spring application.
When this library is loaded within another Spring application everything works.
When I try to initialize application context with Non-spring boot enabled application and get my bean I get the following warnings and exception:
org.springframework.core.LocalVariableTableParameterNameDiscoverer - Cannot find '.class' file for class [class com.acme.common.library.spring.service.InstrumentIdLookupServiceImpl$$EnhancerBySpringCGLIB$$59e4e4ac] - unable to determine constructor/method parameter names
org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'instrumentIdLookupServiceImpl' via constructor to bean named 'instrumentIdLookupServiceProperties'
WARN org.springframework.context.support.GenericApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.acme.common.library.spring.InstrumentIdBinding': Invocation of init method failed; nested exception is java.lang.IllegalStateException: No factory found for binding target type: org.apache.kafka.streams.kstream.KStream among registered factories: channelFactory,messageSourceFactory
No factory found for binding target type: org.apache.kafka.streams.kstream.KStream among registered factories: channelFactory,messageSourceFactory
public interface InstrumentIdBinding {
String INSTRUMENT_IDS = "instrument-ids";
#Input(INSTRUMENT_IDS)
KStream<String, InstrumentIdMsg> processInstrumentId();
}
<?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="com.acme.common.library.spring"/>
</beans>
GenericApplicationContext ctx = new GenericApplicationContext();
final XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new FileSystemResource("applicationContext-ext.xml"));
ctx.refresh();
InstrumentIdLookupService bean = ctx.getBean(InstrumentIdLookupService.class);

Spring Cloud Stream requires Spring Boot.

Related

Spring NotWritablePropertyException and Invalid property 'lazyInit' of bean JndiObjectFactoryBean

We are using WAS8.5 based JNDI data source configuration. While server start up, this datasource is not getting created. Hence throwing
org.springframework.beans.factory.BeanCreationException by saying "Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'lazyInit' of bean class [org.springframework.jndi.JndiObjectFactoryBean]: Bean property 'lazyInit' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?"
We are not trying to set lazyInit property in our application. What could be the issue here? Is anything missed here?
Spring-context.xml:
<beans
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans">
<context:annotation-config/>
<jee:jndi-lookup id="ds_app1" jndi-name="java:comp/env/jdbc/ds_app1" />
<!-- SQL Session factories -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property ref="ds_app1" name="dataSource"/>
<property name="configLocation" value="classpath:/conf/xml/mybatis-config.xml" />
<property name="mapperLocations" value="classpath:/conf/xml/mapper/*.xml"/>
</bean>
</beans>
Same piece of code is working in another environment with same WAS8.5 server with same set of data source configurations. In our application, we are using spring4.3.8,mybatis3.x and java8. Here we are injecting datasource beans using xml configuration(dao-spring-context.xml)
Expected output would be data source should be injected to sql session factory bean.but actual result is getting the below exception.
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sqlSessionFactory' defined in class path resource [conf/xml/dao-spring-context.xml]: Cannot resolve reference to bean 'ds_app1' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ds_app1': Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'lazyInit' of bean class [org.springframework.jndi.JndiObjectFactoryBean]: Bean property 'lazyInit' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?
This approach worked for me
1) Create a post processor
package org.test;
import org.springframework.bean.PropertyValue;
import org.springframework.bean.PropertyValues;
import org.springframework.bean.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import java.beans.PropertyDescriptor;
#Component
public class CustomJndiInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
#Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
if (bean instanceOf org.springframeworkf.jndi.JndiObjectFactoryBean) {
for (PropertyValue pv: pvs.getPropertyValues()) {
if ("lazyInit".equals(pv.getName())) {
pv.setOptional(true);
}
}
}
}
}
2) Include this bean in your spring context xml
<bean id="customJndiInstantiationAwareBeanPostProcessor" class="org.test.CustomJndiInstantiationAwareBeanPostProcessor"/>

Getting a Session-scoped Bean Results in "No Scope registered for scope 'session' "

I'm in an older Spring app which doesn't use annotations.
My task is very simple, get a Session Bean from applicationContext.xml (inside a Struts action), but getting this error:
java.lang.IllegalStateException: No Scope registered for scope 'session'
applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<!-- Session-scoped bean -->
<bean id="techSuppRoleUserInPROD" class="myapp.util.TechSuppRoleUserInPROD"
scope="session" />
Attempting to get it from this sample Struts Action:
public class LandingAction extends ActionSupport {
public String execute() {
// 1. Obtain ApplicationContext
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
// 2.Obtain managed session bean
TechSuppRoleUserInPROD techSuppRoleUserInPROD = (TechSuppRoleUserInPROD)
applicationContext.getBean("techSuppRoleUserInPROD");
}
}

EJB3 interceptor cannot bootstrap context

I'm trying to inject Spring beans into an EJB using
#Interceptors(SpringBeanAutowiringInterceptor.class)
Here's my EJB:
#Stateless
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class processMethodService implements
processMethodService {
#Autowired
private SomeBean bean;
#Schedule(minute = "*/5", hour = "*", persistent = false)
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void startProcessing() {
//businesslogic
}
}
And beanRefContext.xml as follows
<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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<bean id="ejb-businesslayer.application.context" lazy-init="true"
class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>classpath:/META-INF/spring-config.xml</value>
</list>
</constructor-arg>
</bean> `
beanRefContext.xml,spring-config.xml are under META-INF folder.
when startProcessing is called for every 5 minutes and we are getting the below exception
Exception data: javax.ejb.EJBException: session bean lifecycle interceptor failure;nested exception is:org.springframework.beans.factory.access.BootstrapException: Unable to return specified BeanFactory instance: factory key [null],
from group with resource name [classpath*:beanRefContext.xml];
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [org.springframework.beans.factory.BeanFactory] is defined
Please find the complete exception as below
Exception data: javax.ejb.EJBException: session bean lifecycle interceptor failure;nested exception is: org.springframework.beans.factory.access.BootstrapException: Unable to return specified BeanFactory instance: factory key [null], from group with resource name [classpath*:beanRefContext.xml]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.beans.factory.BeanFactory] is defined`enter code here`
at com.ibm.ejs.container.util.ExceptionUtil.EJBException(ExceptionUtil.java:466)
at com.ibm.ejs.container.SessionBeanO.callLifecycleInterceptors(SessionBeanO.java:288)
at com.ibm.ejs.container.StatelessBeanO.initialize(StatelessBeanO.java:399)
at com.ibm.ejs.container.BeanOFactory.create(BeanOFactory.java:147)
at com.ibm.ejs.container.EJSHome.createBeanO(EJSHome.java:1238)
at com.ibm.ejs.container.EJSHome.createBeanO(EJSHome.java:1356)
at com.ibm.ejs.container.activator.UncachedActivationStrategy.atActivate(UncachedActivationStrategy.java:88)
at com.ibm.ejs.container.activator.Activator.preInvokeActivateBean(Activator.java:615)
at com.ibm.ejs.container.EJSContainer.preInvokeActivate(EJSContainer.java:4205)
at com.ibm.ejs.container.EJSContainer.EjbPreInvoke(EJSContainer.java:3535)
at com.ibm.ejs.container.TimedObjectWrapper.invokeCallback(TimedObjectWrapper.java:110)
at com.ibm.ejs.container.TimerNpListener.doWork(TimerNpListener.java:293)
at com.ibm.ejs.container.TimerNpListener.doWorkWithRetries(TimerNpListener.java:171)
at com.ibm.ejs.container.TimerNpListener.fired(TimerNpListener.java:141)
at com.ibm.ws.asynchbeans.AlarmImpl.callListenerMethod(AlarmImpl.java:427)
at com.ibm.ws.asynchbeans.timer.GenericTimer.run(GenericTimer.java:228)
at com.ibm.ws.asynchbeans.J2EEContext.run(J2EEContext.java:1178)
at com.ibm.ws.asynchbeans.AlarmImpl.runListenerAsCJWork(AlarmImpl.java:249)
at com.ibm.ws.asynchbeans.am._Alarm.fireAlarm(_Alarm.java:333)
at com.ibm.ws.asynchbeans.am._Alarm.run(_Alarm.java:230)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1783)
Caused by: org.springframework.beans.factory.access.BootstrapException: Unable to return specified BeanFactory instance: factory key [null], from group with resource name [classpath*:beanRefContext.xml]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.beans.factory.BeanFactory] is defined
at org.springframework.beans.factory.access.SingletonBeanFactoryLocator.useBeanFactory(SingletonBeanFactoryLocator.java:402)
at org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.getBeanFactoryReference(SpringBeanAutowiringInterceptor.java:160)
at org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.getBeanFactory(SpringBeanAutowiringInterceptor.java:141)
at org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.doAutowireBean(SpringBeanAutowiringInterceptor.java:121)
at org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.autowireBean(SpringBeanAutowiringInterceptor.java:95)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:88)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:613)
at com.ibm.ejs.container.interceptors.InterceptorProxy.invokeInterceptor(InterceptorProxy.java:227)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.proceed(InvocationContextImpl.java:548)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.doLifeCycle(InvocationContextImpl.java:273)
at com.ibm.ejs.container.SessionBeanO.callLifecycleInterceptors(SessionBeanO.java:274)
Please guide me on how to resolve this error
The ContextSingletonBeanFactoryLocator is looking for resource classpath*:beanRefContext.xml, so the beanRefContext.xml file has to be in the classpath, ref this link,
Move beanRefContext.xml into a folder that's in the class path and that should solve the problem.
First off, I think removing META-INF should help. Also, I just solved this same issue by moving context in question to /resources directory

Autowiring request scoped beans into application scoped beans

Is it possible to autowire a request scoped bean into an application scoped bean. i.e
I have a class RequestScopedBean:
class RequestScopedBean {
....
....
....
}
and a class Application scoped bean in which the request scoped bean is autowired.
class ApplicationScopedBean {
#Autowire
private RequestScopedBean requestScopedBean;
....
....
....
}
and the spring-config xml is as follows:
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
">
<bean id="applicationScopedBeans" class="ApplicationScopedBean" />
<bean id="requestScopedBean" class="RequestScopedBean" scope="request">
</bean>
</beans>
when I try to run this application the bean creation of applicationScopedBean fails with the following error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ApplicationScopedBean': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private RequestScopedBean requestScopedBean; nested exception is java.lang.IllegalStateException: No Scope registered for scope 'request'
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:312)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1075)
at com.amazon.coral.reflect.instantiate.SpringInstantiatorFactory$1.newInstance(SpringInstantiatorFactory.java:168)
... 19 more
You have to mark your requestScopedBean as a scoped proxy also, this way Spring will inject in a proxy for requestScopedBean and in the background manage the scope appropriately.
<bean id="requestScopedBean" class="RequestScopedBean" scope="request">
<aop:scoped-proxy/>
</bean>
More here
The exception above suggests that you have not correctly configured Spring for the provision of request scoped beans.
You need to add this to your web.xml as described in the docs here:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
However, there is more to your question than just configuration. You are attempting to inject a request scoped bean into a singleton scoped bean. Spring resolves dependencies and instantiates singletons when the DI container starts. This means that ApplicationScopedBean will only be created once (at this point there will be no request in flight and so the autowiring will most likely fail).
If you were using a prototype scoped bean instead of request scoped you'd have to consider a way of suppling the singleton scoped bean with a fresh instance everytime it was used. The approaches for this are described in the Method Injection chapter of the Spring docs.
#Airwavezx the annotation equivalent is the followinng:
#Scope( value = SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS )

Spring component detection without xml bean definitions

Is it correct that one can create spring beans using just the #Component annotation as long as context component scanning is configured?
Using spring 3.0.5 with Java 6.
My test case is:
#ContextConfiguration(locations={"classpath:spring-bean.xml"})
public class ServerServiceUnitTest extends AbstractJUnit4SpringContextTests {
#Autowired
private ServerService serverService;
#Test
public void test_server_service() throws Exception {
serverService.doSomething();
//additional test code here
}
}
The spring-bean.xml file contains:
<?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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
</beans>
My class I want to be a bean is:
#Component("ServerService")
public class ServerServiceImpl implements ServerService {
private static final String SERVER_NAME = "test.nowhere.com";
//method definitions.....'
}
Should that not be sufficient for spring to instantiate the ServerService bean and do the autowiring?
The error I get is:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [serversystem.ServerService] 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)}
I'm sure I'm missing something simple.
You have not defined in your spring-beans.xml the <context:component-scan> element:
<context:component-scan base-package="the.package.with.your.service"/>
The inclusion of
<context:annotation-config/>
only allows you to use #Required, #Autowired, and #Inject annotations for configuration. By specifying the <context:component-scan>, you are telling Spring where to look for #Component annotations.
if you are using annotated controllers and other features
you should include
<mvc:annotation-driven/>
you should use
<context:component-scan base-package="spring3.example.controllers"/>
to specify the package in which controller classes are stored.

Resources