Inject property into applicationContext.xml as value (spring boot 2.2) - java

I am trying to inject a property into my applicationContext.xml file in my spring boot project:
Application file :
#SpringBootApplication
#PropertySource("classpath:navi.properties") // <== injection here
#ImportResource({"classpath*:applicationContext.xml"}) // <== load the xml setting file
public class CApplication {
public static void main(String[] args) {
SpringApplication.run(CApplication.class, args);
}
}
As you can see, nothing fancy here... In my src/main/resources/navi.properties file :
USER_INFO_CLS=jp.co.xxx.yyy.fw.service.UserInfoService
in my applicationContext.xml, I am trying to inject this value :
<bean id="userInfoService" class="${USER_INFO_CLS}"/>
But ./mvnw spring-boot:run returns the error below :
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [${USER_INFO_CLS}] for bean with name 'userInfoService' defined in class path resource [applicationContext.xml]; nested exception is java.lang.ClassNotFoundException: ${USER_INFO_CLS}
I read many articles about it (like this one) and it sounds good....
Thanks

Related

Spring boot: #Value having issues with bean defined in dependency

I have a spring boot application, say A, which has a bean defined in xml:
<bean class="com.learning.MyBean" name="myBean">
<property name="maxAngle" value="360" ></property>
</bean>
Bean is:
public class MyBean {
#Value("${maxAngle}")
public void setMaxAngle(double maxAngle) {
....
}
}
When I run A independently, all is fine. But when I include it as dependency in another spring boot application, then I get error related to injection of maxAngle:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myBean': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'maxAngle' in value "${maxAngle}"
What can be the issue here?
#Value annotation is used to bind properties defined in application.properties or application.yaml.
Try adding maxAngle=360 to application.properties or application.yaml and remove it from bean XML defination

Unsatisfied Dependency Exception in Spring boot

I have a properties XML file as following :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="sample.findAll">
<![CDATA[
The SQL query goes here
]]>
</entry>
</properties>
And a config file as following :
#ImportResource("classpath:sql/find-all-sample-native-query.xml")
#Configuration
public class SampleFindAllConfig {
#Value("#{sample.findAll}")
private String findAllQuery;
#Bean
public String findAllSampleNativeQuery() {
return findAllQuery;
}
}
I'm injecting the Bean in the DAO class as following :
#Inject
private String findAllAnomalieNativeQuery;
But I get this error when I run my application :
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'sampleDAO': Unsatisfied dependency
expressed through field 'findAllSampleNativeQuery'; nested exception
is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'sampleFindAllConfig': Unsatisfied
dependency expressed through field 'findAllQuery'; nested exception is
org.springframework.beans.factory.BeanExpressionException: Expression
parsing failed; nested exception is
org.springframework.expression.spel.SpelEvaluationException: EL1008E:
Property or field 'sample' cannot be found on object of type
'org.springframework.beans.factory.config.BeanExpressionContext' -
maybe not public?
How can I solve this ?
There are two problems with the code.
Problem 1: Use #PropertySource to load with property values with #Value
#ImportResource imports beans definitions, usually in conjunction with XML Spring configuration.
To load property values for #Value from a configuration file, use #PropertySource.
Problem 2: Reference properties using the ${...} syntax
#{sample.findAll} is a SpEL expression. It asks Spring to evaluate sample.findAll, using sample as a bean. Since there is no bean of that name in the context, Spring rightly complains that there is no such bean.
To load the value of the property sample.findAll from a configuration source, use the syntax ${sample.findAll}.
The following code will work:
#Configuration
#PropertySource("classpath:sql/find-all-sample-native-query.xml")
public class SampleFindAllConfig {
#Value("${sample.findAll}")
private String findAllQuery;
#Bean
public String findAllSampleNativeQuery() {
return findAllQuery;
}
}

Spring: How can I debug a BeanCreationNotAllowedException?

I am trying to add a new Spring bean to one of my projects. The bean is defined and created in another package like so:
#Configuration
public class UtilityBeans {
public static String MY_BEAN_NAME = "my.bean.name";
#Bean(name = MY_BEAN_NAME)
public MyUtilBeanClass getMyBeanClass() {
return new MyUtilBeanClass();
}
}
I use it in my other package like this:
#Configuration
#Import({
UtilityBeans.class
)}
...
#Resource(name = UtilityBeans.MY_BEAN_NAME)
private MyUtilBeanClass myUtilBeans;
During runtime I get:
ERROR
Caused by: org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'my.bean.name': Singleton bean creation not allowed while the singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
...
The logs do not give me any useful information as the stack trace is all in Spring library. How can I find out what failed? Is it incorrect usage of resource or is it that the bean creation itself is wrong?
I am using Spring-4 with JDK8.
The issue here was that the bean was being created in 2 different points in my spring configuration due to some refactoring and the fix was to remove duplicate code. I had the same bean creation code:
#Bean(name = MY_BEAN_NAME)
public MyUtilBeanClass getMyBeanClass() {
return new MyUtilBeanClass();
}
... in another class I had half way refactored.
In this case my mistake was that I did not grep across all the log files being generated. The exceptions were being split and then buried into 2 different logs, one for a server start up and one for application runtime. The above exception was being posted to the application log. The other logs contained the relevant exception which stated that duplicate bean creation failed and the fix was to remove duplicate code.

Cannot integrate JMX with Spring application

I have got a SPRING application. When I run
mvn jetty:run
everything is ok.
I would like to use JMX in my project.
I created another project, I tried tutorial for beginners and I was able to see some changes with jconsole.
Now, I want to use JMX in my real project and I would like to use SPRING libraries which manages JMX - following this post
How to integrate JMX with Spring?
I have got a class:
public class MyMainClass {
private int var1;
private int var2;
private TimeUnit var3;
// public getters and setters
public static MyXXXClass<String, Object> getInstance();
}
and in config.xml
<!-- other beans -->
<bean id="myid" class="com.my.package.MyMainClass">
<property name="var1" value.../>
<property name="var2" value... />
<property name="var3" value.../>
</bean>
<!-- other beans -->
I changed few things to make it works with JMX.
I added an interface:
import java.util.concurrent.TimeUnit;
public interface IMyMainClassBean {
public int getVar1();
public void setVar1(int var1);
public int getVar2();
public void setVar2(int var2);
public TimeUnit getVar3();
public void setVar3(TimeUnit var3);
}
I added implements to my class:
public class MyMainClassBean implements IMyMainClassBean {...}
Last thing, I edited my xml file:
<!-- other beans -->
<bean id="myid" class="com.my.package.MyMainClassBean">
<property name="var1" value.../>
<property name="var2" value... />
<property name="var3" value.../>
</bean>
<!-- this bean must not be lazily initialized if the exporting is to happen -->
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"
lazy-init="false">
<property name="beans">
<map>
<entry key="bean:name=testBean1" value-ref="myid" />
</map>
</property>
</bean>
<!-- other beans -->
Now, when I start my server, it gives me a lot of exceptions (log is really long, so I copied just a part which I think is the most important).
Caused by: org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [com.my.package
.MyMainClassBean#3d4395fb] with key 'bean:name=testBean1'; nested exception is javax.management.InstanceAlreadyExistsExcep
tion: bean:name=testBean1
at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:602)
at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:527)
at org.springframework.jmx.export.MBeanExporter.afterPropertiesSet(MBeanExporter.java:413)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableB
eanFactory.java:1571)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBean
Factory.java:1509)
... 163 more
Caused by: javax.management.InstanceAlreadyExistsException: bean:name=testBean1
at com.sun.jmx.mbeanserver.Repository.addMBean(Repository.java:453)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.internal_addObject(DefaultMBeanServerInterceptor.java:1484)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:963)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:917)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:312)
at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:483)
at org.springframework.jmx.support.MBeanRegistrationSupport.doRegister(MBeanRegistrationSupport.java:195)
at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:655)
at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:592)
... 167 more
[WARNING] Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myTask' defined
in class path resource [anotherconfigfile.xml]: Cannot resolve reference to bean 'anotherimport' while setting bean property 'targetObj
ect'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'anotherimport' defin
ed in class path resource [anotherconfigfile.xml]: Cannot create inner bean 'myTotallyAnotherClass' of type [com.my.package.another.MyTotallyAnotherClass]
while setting bean property 'myTotallyAnotherClass'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creatin
g bean with name 'myTotallyAnotherClass' defined in class path resource [anotherconfigfile.xml]: Instantiation of bean failed; nested exception is
org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.my.package.another.MyTotallyAnotherClass]: Co
nstructor threw exception; nested exception is java.lang.ExceptionInInitializerError:
javax.management.InstanceAlreadyExistsException: bean:name=testBean1
at com.sun.jmx.mbeanserver.Repository.addMBean(Repository.java:453)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.internal_addObject(DefaultMBeanServerInterceptor.java:1484)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:963)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:917)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:312)
at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:483)
at org.springframework.jmx.support.MBeanRegistrationSupport.doRegister(MBeanRegistrationSupport.java:195)
at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:655)
at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:592)
at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:527)
at org.springframework.jmx.export.MBeanExporter.afterPropertiesSet(MBeanExporter.java:413)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableB
eanFactory.java:1571)
I have no even idea how to debug it.
Thank you for all your hints.
Caused by: javax.management.InstanceAlreadyExistsException: bean:name=testBean1
This is trying to tell you that you have 2 beans with the same name ObjectName of bean:name=testBean1 being register with the MBeanExporter. However, unless there are other XML files or more entries in your beans map then there should not be.
I have no even idea how to debug it.
You could put a breakpoint in the JmxMBeanServer.registerMBean(...) method to see what beans are being registered to see if you can figure out why you are getting a duplicate.
As an aside, my SimpleJMX library is an easy way to export your beans via JMX. There is pretty good Spring support as well. Here are the documentation about using with Spring. There is also a Spring test program which demonstrates what you need to do to get it working. Here's the Spring XML file.
This is happening as the bean is trying to initialize even after its initialized once.
I was facing the same issue with RabbitMQ configuration in Spring TestNG testcases.
Use #DirtiesContext as a class level annotation for every testcase class.
This will create applicationcontext and kill it once the testcase class is run and a new applicationcontext will be created for the next testcase class.
Example -
#Test
#ContextConfiguration(classes = { ApplicationConfig.class })
#DirtiesContext
#WebAppConfiguration
public class ATest extends AbstractTestNGSpringContextTests{
#BeforeSuite
public void setup() throws Throwable {
}
#AfterSuite
public void teardown() {
}
}

Added Spring Security, now I'm getting "No WebApplicationContext found: no ContextLoaderListener registered?"

I have a Spring web application that is running just fine. I'm using JavaConfig, so there's not a lick of XML in the whole configuration. I'm trying to integrate Spring Security, but when I add a class that extends AbstractSecurityWebApplicationInitializer as directed by this tutorial, I get the following exception:
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:251)
...
Any idea how I can resolve this?
You probably need to ensure the security configuration is loaded. If the security configuration is not being loaded by other means, the AbstractSecurityWebApplicationInitializer should pass in the Security configuration to the super class as shown in the guide:
import org.springframework.security.web.context.*;
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
public SecurityWebApplicationInitializer() {
super(SecurityConfig.class);
}
}
I was also having the same problem following the guide from the site.
Adding the code to the MessageSecurityWebApplicationInitializer.java solved the problem.
public MessageSecurityWebApplicationInitializer() {
super(SecurityConfig.class);
}
When I tried to add super(SecurityConfig.class) I get no default constructor found and I checked the class and there was a constructor with config parameter and no default, hence failed. Did anything change in 3.2.6?
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfig': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.access.SecurityConfig]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.security.access.SecurityConfig.()
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1093)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1038)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)

Categories