Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JBoss AS 7 application specific properties file

I have several independent Java EE modules (WAR web applications, and JAR EJB modules) which I deploy on JBoss 7.1.1 AS. I want to:

  1. Centralize configuration of these modules in one *.properties file.
  2. Make this file available in classpath.
  3. Keep the installation/configuration of this file as simple as possible. Ideally would be just to put it in some JBoss folder like: ${JBOSS_HOME}/standalone/configuration.
  4. Make changes to this file available without restarting the application server.

Is this possible?

I already found this link: How to put an external file in the classpath, which explains that preferable way to do this is to make static JBoss module. But, I have to make dependency to this static module in every application module that I deploy, which is a kind of coupling I'm trying to avoid.

like image 896
stasam Avatar asked Mar 12 '13 15:03

stasam


2 Answers

Maybe a simple solution is to read the file from a singleton or static class.

private static final String CONFIG_DIR_PROPERTY = "jboss.server.config.dir"; 

private static final String PROPERTIES_FILE = "application-xxx.properties";

private static final Properties PROPERTIES = new Properties();

static {
    String path = System.getProperty(CONFIG_DIR_PROPERTY) + File.separator + PROPERTIES_FILE;  
    try {  
        PROPERTIES.load(new FileInputStream(path));
    } catch (MalformedURLException e) {
       //TODO 
    } catch (IOException e) {
       //TODO
    } 
}
like image 120
Max Avatar answered Oct 18 '22 01:10

Max


Here is a full example using just CDI, taken from this site.

This configuration will also work for JBoss AS7.

  1. Create and populate a properties file inside the WildFly configuration folder

    $ echo 'docs.dir=/var/documents' >> .standalone/configuration/application.properties
    
  2. Add a system property to the WildFly configuration file.

    $ ./bin/jboss-cli.sh --connect
    [standalone@localhost:9990 /] /system-property=application.properties:add(value=${jboss.server.config.dir}/application.properties)
    

This will add the following to your server configuration file (standalone.xml or domain.xml):

<system-properties>
    <property name="application.properties" value="${jboss.server.config.dir}/application.properties"/>
</system-properties>
  1. Create the singleton session bean that loads and stores the application wide properties

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    
    import javax.annotation.PostConstruct;
    import javax.ejb.Singleton;
    
    @Singleton
    public class PropertyFileResolver {
    
        private Logger logger = Logger.getLogger(PropertyFileResolver.class);
        private String properties = new HashMap<>();
    
        @PostConstruct
        private void init() throws IOException {
    
            //matches the property name as defined in the system-properties element in WildFly
            String propertyFile = System.getProperty("application.properties");
            File file = new File(propertyFile);
            Properties properties = new Properties();
    
            try {
                properties.load(new FileInputStream(file));
            } catch (IOException e) {
                logger.error("Unable to load properties file", e);
            }
    
            HashMap hashMap = new HashMap<>(properties);
            this.properties.putAll(hashMap);
        }
    
        public String getProperty(String key) {
            return properties.get(key);
        }
    }
    
  2. Create the CDI Qualifier. We will use this annotation on the Java variables we wish to inject into.

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import javax.inject.Qualifier;
    
    @Qualifier
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR })
    public @interface ApplicationProperty {
    
        // no default meaning a value is mandatory
        @Nonbinding
        String name();
    }
    
  3. Create the producer method; this generates the object to be injected

    import javax.enterprise.inject.Produces;
    import javax.enterprise.inject.spi.InjectionPoint;
    import javax.inject.Inject;
    
    public class ApplicationPropertyProducer {
    
        @Inject
        private PropertyFileResolver fileResolver;
    
        @Produces
        @ApplicationProperty(name = "")
        public String getPropertyAsString(InjectionPoint injectionPoint) {
    
            String propertyName = injectionPoint.getAnnotated().getAnnotation(ApplicationProperty.class).name();
            String value = fileResolver.getProperty(propertyName);
    
            if (value == null || propertyName.trim().length() == 0) {
                throw new IllegalArgumentException("No property found with name " + value);
            }
            return value;
        }
    
        @Produces
        @ApplicationProperty(name="")
        public Integer getPropertyAsInteger(InjectionPoint injectionPoint) {
    
            String value = getPropertyAsString(injectionPoint);
            return value == null ? null : Integer.valueOf(value);
        }
    }
    
  4. Lastly inject the property into one of your CDI beans

    import javax.ejb.Stateless;
    import javax.inject.Inject;
    
    @Stateless
    public class MySimpleEJB {
    
        @Inject
        @ApplicationProperty(name = "docs.dir")
        private String myProperty;
    
        public String getProperty() {
            return myProperty;
        }
    }
    
like image 45
Chris Ritchie Avatar answered Oct 18 '22 01:10

Chris Ritchie