24 April 2014

Filter Properties and pass them into Java Apps with Maven

If you create an app that will connect to other secured services, the day will come you have to add some developer keys or passwords. Or you want to simply define different environments (production, development, test) for your app running into e.g. for testing purposes. Changing that properties every time or pushing that properties to the repository would be a flaw.

Seriously, you should never push passwords etc. to your repository, no matter if it's private or not!

So what to do to prevent this? Passing that properties with Maven is one solution. Let's start!
Create a Maven Web Application Project if you haven't and open your pom.xml You will probably see a properties section, if not create one and add these properties:

./pom.xml

    ...
    Development
    default2

Now go to the build section and add

./pom.xml

    ...
    
        
            src/main/resources
            true
        
    
    ...

also add the following plugin to the build -> plugins section

./pom.xml

    ...
    
        ...
        
            org.apache.maven.plugins
            maven-resources-plugin
            2.6
            
                UTF-8
            
        
        ...
        
            org.apache.maven.plugins
            maven-war-plugin
            2.3
            
                false
                 
                     
                        ${basedir}/src/main/webapp/WEB-INF 
                         
                            web.xml 
                         
                        WEB-INF 
                        true 
                     
                 
            
        
        ...
    

Now the whole maven-part is done but we need some files to test our configuration.
Create a web.xml file under src/main/webapp/WEB-INF/ and fill in the following:

src/main/webapp/WEB-INF/web.xml
...
    
        javax.faces.PROJECT_STAGE${jsf.projectstage}
    
    
        Faces Servlet
        javax.faces.webapp.FacesServlet
        1
    
    
        Faces Servlet
        *.xhtml
    
    
        index.xhtml
    
    ...

Also add a index.xhtml file within src/main/webapp/ with the following code:

src/main/webapp/index.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>#{facesContext.application.projectStage}</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    </head>
    <body>
        <div>
            Project Stage: #{facesContext.application.projectStage}
        </div>
    </body>
</html>

Now you can Clean & Build the application and deploy it on your Application Server. The starting page index.xhtml will show you your actual project stage. The app will get the property <jsf.projectstage>Development</jsf.projectstage> from Maven and pass it into the web.xml. The web.xml is a Web Resource so the maven-war-plugin is responsible for that. Thus you can quickly change the JSF-Environment of your JSF-Application in the properties section of the Maven pom.xml. In addition you can pass that property when you trigger the build. For this simply execute the following line on the Terminal in your project dir:

mvn clean install -Djsf.projectstage=Production

Now we know the maven-war-plugin filters the web.xml but whats with that other stuff (maven-resources-plugin etc.)? With that you can filter not just Web Resource, you can filter usual resources. So let's do it. Create a filtered_resource.properties file under src/main/resources/

src/main/resources/filtered_resource.properties
filtered_value = ${property.2}

Now we need something to read the property. For that we create a Stateless EJB:

src/main/java/de/beanbelt/bbpassingpropertieswithmaven/OurService.java
@Stateless
public class OurService {

 public void readProperties() throws IOException {
  ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  InputStream stream = classLoader.getResourceAsStream("filtered_resource.properties");

  Properties properties = new Properties();
  properties.load(stream);

  String value = properties.getProperty("filtered_value", "not_filtered");

  System.out.println("Value: " + value);
 }
}

When you call the readProperties() method it will print the following on the console if everything is okay:

Reading properties...
Value: default2
...if not it will print:
Reading properties...
Value: not_filtered

That's it! Now you can pass properties into your Java Apps with Maven.

Happy Coding!

No comments :

Post a Comment