How to check if all spring placeholders exist? - java

I have java spring application, that uses in xml files placeholders values of them taken from app.properties. Is it possible to create test or something similar without starting application and getting up spring context that names all placeholders used in xml files (where beans are configured) are correct, nothing missing, nothing misspelled etc. ?
Thanks.

One idea would be to get a reference to the ApplicationContext and actually create every bean. This should throw an exception if something was not defined correctly.
String[] beanNames = getAppContext().getBeanDefinitionNames();
for (int i = 0; i < beanNames.length; i++)
{
BeanDefinition beanDefinition = getAppContext().getBeanFactory()
.getBeanDefinition(beanNames[i]);
if (!beanDefinition.isAbstract())
{
getAppContext().getBean(beanNames[i]);
}
}

Related

Is there a way to provide default values for env variables in a properties file with apache-commons?

I'm using org.apache.commons:commons-configuration2:2.5 to read config parameters from a config file. In my application.properties, I want to specify default values for environment variables in case one of these has not been set, e.g. like so (similar as with Spring):
idp.username=${env:IDP_USERNAME:defaultUsername}
However, while setting the env variable works fine, specifying a default value like this is not working. Unfortunately, I can't find anything related to this in the commons-configuration2 documentation. Is this possible without explicitly checking for a missing value in the Java code? Does Spring Boot use a certain lib for this that I could also use? I don't want to bloat up my simple app with the Spring framework only to have this kind of configuration.
Simplified code example I'm currently using (here, I obviously could check each property I retrieve and replace it with a default, but I'd like to avoid this and handle it directly in the config file):
private void loadConfigFile() {
logger.info("Attempting to load `application.properties`...");
Configurations configBuilder = new Configurations();
try {
Configuration props = configBuilder.properties(new File("application.properties"));
// application config
this.conf = new Config();
this.conf.setAPIEndpoint(props.getString("api.endpoint"));
this.conf.setMaxConnections(props.getInt("api.maxConnections"));
...
logger.info("Config successfully loaded!");
} catch (Exception e) {
logger.error("Could not load `application.properties`: {}", e.getMessage());
System.exit(1);
}
}
Any suggestions?
Commons Configuration provides a way to do custom interpolation. This answer shows an example. Your Lookup implementation would need to handle parsing everything past the prefix and then doing the lookup and providing the default value.

How to allocate spring-context?

I am absolutely confused with application context in spring. If i use spring (simple spring) create a beans.xml and then invoke Application context from (for example) main() method.
ApplicationContext context = new FileSystemXmlApplicationContext
("C:/Users/ZARA/workspace/HelloSpring/src/Beans.xml");
all works well. But I don't understand if i move file on directory above or in another directory(for example) it will be ok?
in spring-mvc there is context for each DispatcherServlet which i create and where i specify some beans, there is common context for all servlets, how to specify this? in web.xml?
in general, please explain me this moment (I read spring in action, i undesrstand almost all, but these tricky moment isn't shown there.
From FileSystemXmlApplicationContext java doc:
Standalone XML application context, taking the context definition files from the file system or from URLs, interpreting plain paths as relative file system locations (e.g. "mydir/myfile.txt"). Useful for test harnesses as well as for standalone environments.
The key words here are context definition files, so you can pass paths to as many xml-files, as you want. Besides that, you can create an application context and pass it to the new one as a parent:
FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent)
Thus you can easily create the needed hierarchy of contexts.
ApplicationContext parentContext = new FileSystemXmlApplicationContext
("C:/some/path/ParentBeans.xml");
ApplicationContext childContext = new FileSystemXmlApplicationContext
(new String[]{"C:/some/path/ChildBeans1.xml", "C:/some/path/ChildBeans2.xml"}, parentContext);
if i move file on directory above all in another directory(for example) it will be ok?
As long as your path to file is correct and reachable - it's Ok.

Spring 3.0 #Value read from property file gettng exception on deployment

I am trying to build a spring 3.0 application version 3.1.0.RELEASE , where i want to read from a property file and using the #Value annotation read from it in my Component class. For this the changes i made:
in mvc-dispatcher-servlet.xml:
<context:property-placeholder location="classpath:mediamonitoring.properties"/>
Component class:
#Component
public class SomeHelper {
#Value("${baseUri}")
private String baseUri;
public String getBaseUri() {
return baseUri;
}
public void setBaseUri(String baseUri) {
this.baseUri = baseUri;
}
}
Property:
baseUri:http://localhost:8080/
and i have wired this helper class to a #service class using the #Autowired annotation.
When i build and deploy the application i get the following error:
java.lang.IllegalArgumentException: Could not resolve placeholder 'baseUri'
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
Is there anything which i am missing because i just followed the standard proceedure.
Appreciate any help in advance.
-Vaibhav
Use = instead of : as separator
baseUri=http://localhost:8080/
can't comment, need more rep, so using the asnwer option. check where did u put your mediamonitoring.properties. I mean, check if it's in your classpath
You should escape special characters : and = with \ in value like this:
baseUri:http\://localhost\:8080/
Otherwise parser can't decide where you value ends and where new key starts.
See also Java properties file specs
Assuming you are following the normal practices of having a ContextLoaderListener and a DispatcherServlet make sure that the <context:property-placeholder location="classpath:mediamonitoring.properties"/> is in the correct application-context. It will only operate on beans in the same application-context, not on beans in a parent or child context.
Replace : with = and use # instead of $
#{baseUri}
You can also try to use:
<util:properties id="props"
location="classpath:/yourproperties.properties" />
And than:
#Value("#{props['yourProperty']}")

Spring : How to inject manually a bean which is not managed by actual application?

Here the context :
we have a java library, which is a factory code.
this library is deployed directly on Tomcat
Application "A", "B" & "C" use this library (jar) to compile, and it is the deployed version on Tomcat which is used when an application call it.
In the library, we have these packages :
- old.service
- old.service.impl
- new.service
- new.service.impl
The old services are some classic classes with setters. It is a spring bean declared in XML configuration of application "A".
In the new services, we have an annotated class (#Service) with some #Autowired attributes in order to be managed by application "B" & "C" which have an autoscan in XML configuration.
We would like to change the implementation of a old services, in order to use the new one without changing anything in application "A".
For that, we can call the new class from the older. But the pb is Spring......
How can we instanciate the new class, and the #autowired attributes ?
Can we instanciate manually the new class in older class, and instanciate attributes by reflection ?
Thank you.
ps: there is no XML configuration in the java library.
Two ways:
In app A where you instantiate old.service.impl Spring bean inject reference to new.service.impl into it
< bean class="old.service.impl">
< property name="newService" ref="newServiceBean"/>
< /bean>
< bean class="new.service.impl" id="newServiceBean" />
Obviously this means you will have to modify your old.service.impl to add setter for "newService", then use it in old service impl code
Get "new.service.impl" reference directly from web application context:
WebApplicationContextUtils.getWebApplicationContext(servletContext).getBean(newServiceImpl.class);
You will need to obtain ServletContext in this case. One way to do it is to get it from HttpRequest
Option 1 is preferred - you are not relying on running inside a servlet then, and requires very few changes in your code.

Properties framework in java apps

I have been using spring for a while as my IOC. It has also a very nice way of injecting properties in your beans.
Now I am participating in a new project where the IOC is Guice. I dont understand fully the concept how should I inject properties in to my beans using Guice.
The question : Is it actually possible to inject raw properties ( strings , ints ) into my guice beans. If the answer is no , than maybe you know some nice Properties Framework for java.
Because right now I wanted to use the ResourceBundle class for simple properties management in my app. But after using spring for a while this just dont seem seriously enought for me.
this SO post discusses the use of various configuration frameworks, also the use of properties. I'm not sure it's to the point exactly for your needs, but perhaps you can find something of value there.
Spring provides for injection of configuration information found in XML files. I don't want the people installing my software to have to edit XML files, so for the kind of configuration information more properly in a plain text file (such as path information), I've gone back to using java.util.Properties since it's easy to use and fits into Spring pretty well, if you use a ClassPathResource, which permits path-free location of the file itself (it just has to be in the classpath; I put mine at the root of WEB-INF/classes.
Here's a quick method that returns a populated Properties object:
/**
* Load the Properties based on the property file specified
* by <tt>filename</tt>, which must exist on the classpath
* (e.g., "myapp-config.properties").
*/
public Properties loadPropertiesFromClassPath( String filename )
throws IOException
{
Properties properties = new Properties();
if ( filename != null ) {
Resource rsrc = new ClassPathResource(filename);
log.info("loading properties from filename " + rsrc.getFilename() );
InputStream in = rsrc.getInputStream();
log.info( properties.size() + " properties prior to load" );
properties.load(in);
log.info( properties.size() + " properties after load" );
}
return properties;
}
The file itself uses the normal "name=value" plaintext format, but if you want to use Properties' XML format just change properties.load(InputStream) to properties.loadFromXML(InputStream).
Hope that's of some help.
Injecting properties in Guice is easy. After reading in some properties from a file or however, you bind them using Names.bindProperties(Binder,Properties). You can then inject them using, for example, #Named("some.port") int port.

Categories