I have a simple web-app that includes a dependency jar for some functionality and needs to use a property value defined in main app code.
Thanks in advance to help me out on this.
dependency.jar contains
public class MyClass {
#Value("${abc.def}")
private String abc; // DOES NOT GET RESOLVED. IS ALWAYS NULL
}
dependency-context.xml
my-app.war contains
public class LocalClass {
#Value("${abc.def}")
private String abc; // GETS RESOLVED TO CORRECT PROPERTY VALUE
}
context.xml
imports dependency-context.xml
You may be running into this bug. It makes it very difficult to use the #Value with multiple PropertyPlaceholderConfigurers from different projects using import context. To solve this problem try to autowire the existing PropertyPlaceholderConfigurer into your bean configuration method (assuming you can use #Configuration) and update the object in the method with the values from your project.
#scottmf is on the right lines, but you can't read properties directly from PropertyPlaceholderConfigurer :(
Instead, I created a String #Bean in the war...
<bean id="myProperty" class="java.lang.String">
<constructor-arg value="ABC"/>
</bean>
which can be #Autowired into the jar class:
#Bean
public Object myBean(String myProperty) { ... }
Related
I have created this class:
import org.springframework.stereotype.Component;
...
#Component("notTheNameTestMe") //shouldnt this only work with testMe ?
public class TestMe {
public void showMsg() {
System.out.println("Autowiring works");
}
}
And I'm using it this way in a second class (or better: controller):
import com.example.TestMe; //shouldnt this be not necessary with autowire? But getting error else...
...
#Autowired
private TestMe testMe;
...
this.testMe.showMsg();
But this works perfectly (so maybe Im not really using autowire here?), it even works if I rename the whole TestMe class to TestMeSomething (if I adjust the import in the second class)
I dont really understand what #Autowired does. I thought it just scans for SpringBoot Components (which are named by the string in #Component() and when it finds a match it Injects the dependancy. But in my example the match is impossible and I still can see the message "Autowiring works" in the console. This shouldnt be like this if I would really use autowire here or? What am I understanding in a wrong way? What is the difference to using new TestMe() then? I have the dependancy already with the import or? So not a real dependancy injection, or?
Spring is not operating on the name in the #Component annotation. Rather it's using the name of the class. It's simply finding a class named TestMe because that's the type of the variable you've annotated with #Autowired.
It seems to be a simple question but yet i couldn't find clear answer while searching documentation and forums. I'm migrating from xml to java-based config (Spring 5.1.9). Due to some legacy restrictions in xml config i need to create a bean from some side library's non public class:
SampleClass.class
package side.library
class SampleClass {
//... some code here
}
context.xml
...
<bean id = "sampleId" class "side.library.SampleClass">
...
And this works fine since Spring uses reflection inside and it creates bean without any problems at compile/runtime, but in java-based config usage of such class leads to an access error:
package my.configuration;
import side.library.SampleClass; // 'side.library.SampleClass' is not public in 'side.library'. Cannot be accessed from outside package
#Configuration
public class JavaConfiguration{
#Bean
public SampleClass sampleClass() {
return new SampleClass(); // same error text
}
}
So, what is the proper way to deal with this sutiation? Using reflection libs in #Configuration class to reach this class seems to be a bad idea.
just a workaround: create a wrapper class in the outer project in the same package and use this class in your configuration.
package com.legacy;
public class Wrapper {
private LegacyImpl legacyImpl;
public Wrapper()
this.legacyImpl = new LegacyImpl();
}
public void wrappedMethod() {
this.legacyImpl.wrappedMethod();
}
}
New to spring boot.
We have reusable beans in multiple base dependencies. Since, we need those reusable functionality, we are inheriting those jars in pom.xml.
Ex:
Jar1:
ClassName: UserInfo, RequestInterceptors, ClassName3, ClassName4, ClassNameN.
PackageName: com.somename1.base.comps
Jar2:
ClassName: UserInfo, RequestInterceptors, ClassName3, ClassName4, ClassNameN.
PackageName: com.somename2.base.comps
Since the class name is similar, creates conflict issue, when building.
Unfortunatly, we cannot able to change any class names, since someother teams are using these jar. No permission to create another version of these jars.
Is there any way to include both jar without excluding these conflicting components in #EnableAutoConfiguration or #ComponentScan
annotations?
Could someone share some advice here.
The solution here would be to name your beans. The reason for the conflict would be that the names of the classes are the same. For example:
#Configuration
public class Config{
public com.somename2.base.comps.UserInfo somename2UserInfo(){
return new com.somename2.base.comps.UserInfo();
}
public com.somename1.base.comps.UserInfo somename1UserInfo(){
return new com.somename1.base.comps.UserInfo();
}
}
The beans would then be named somename1UserInfo and somename2UserInfo and you can use these names instead when autowiring, e.g.:
public class SomeImpl{
#Autowired
#Qualifier("somename1UserInfo")
UserInfo userInfo;
/*
* Or you can do this
*/
#Resource(name = "somename1UserInfo")
UserInfo theSameUserInfo
}
This will allow you to autowire whichever bean should be used in whichever class. It may not be ideal to have to declare a qualifier for every place the classes are used, so if one implementation is primarily used, consider looking into the #Primary annotation.
I am new to Spring-bot and I need to add a configuration file inside the resources folder and read values from it.
Right now what I have done is that I have created a 'Configuration.properties' file in the classpath folder and have invoked the properties inside the program
FileReader reader=new FileReader("Configuration.properties");
Properties p=new Properties();
p.load(reader);
return p;
Can somebody please help how can i make it to call from the application.properties file of the spring-boot(or similar files) and thus make my configurations available inside the jar which I create.
PS: The Configurations i have given is project specific and am using them for avoiding the hardcoding inside the code.
Create application.properties file in the resource folder, spring boot will automatically find it.
Say you use these properties
test.stringProperty=will_be_used
test.integerProperty=42
stringProperty=not_used
You can then create a configuration properties class like so
import org.springframework.boot.context.properties.ConfigurationProperties;
#ConfigurationProperties(prefix = "test")
public static class TestProperties {
private String stringProperty;
private Integer integerProperty;
// getters and setters
}
and use it
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
#Configuration
#EnableConfigurationProperties(TestProperties.class)
public class TestConfiguration {
#Autowired
private TestProperties config;
// do whatever with properties
}
The autowired object will then have the values you specified in application.propertiesfile with the name 'prefix'.'name of the variable'.
Or you can use the
#Value("${stringProperty}")
private String value;
which is easier at first, but not very maintainable for higher number of properties.
You can use the #Value annotation to get the property file values.
Ex :
#Value("${rest_api_url}")
private String restApiUrl;
Need to define Property file as per requirement of your app.
You can use the #Value annotation in bean.
refer : Externalized Configuration and Properties and Configuration
Create a file in resource folder by the name application.properties which will be taken automatically as the default property file.
If you want to specify some other file as a property, do the below-mentioned changes.
Snippet :
#SpringBootApplication
#ImportResource("classpath:filename.properties")
public class Example{
public static void main(String[] args) {
SpringApplication.run(Example.class, args);
}
}
I have a properties file called xyz.properties. Right now, I am able to load individual property of this file in my class annotated with #Component which is working perfectly fine.
However, I am thinking of making my project more modular, for which I need to read the whole xyz.properties file as one properties object so that i can pass it along. How can I do so ?
Update
Right now, I am loading individual property from the file like this
my applicationContext.xml has following entry
<context:property-placeholder location="classpath:xyz.properties" order="2" ignore-unresolvable="true"/>
and then i have the respective class as
#Component
public class XyzConfiguration {
#Value("${client.id}")
private String clientId;
#Value("${client.secret}")
private String clientSecret;
...
}
What I mean by pass it along
Right now, for each individual property I have to create a respective field in a class and then annotate it with respective property name. By doing so, I am making my nested module very spring framework specific. I might someday put this module on github for others as well and they may or may not use spring framework. For them it would be easier to create an object of this module by passing required parameters (ideally in case of a Properties object) so that my module will fetch the properties by itself.
You can try below code.
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.core.io.ResourceLoader;
import java.util.Properties;
private String fileLocator;
private Properties prop;
private ResourceLoader resourceLoader;
public void init() throws IOException {
//"fileLocator" must be set as a path of file.
final Resource resource = resourceLoader.getResource(fileLocator);
prop = PropertiesLoaderUtils.loadProperties(resource);
}
prop will have all values from your property file and then you can get any value by calling prop.getProperty() method.