VRaptor

Working with environments

Environment is a VRaptor’s feature that allow you to define different components and settings based on the environment like: production, testing, development, and so on.

You can, for example, deactivate the e-mail service in the development environment and enable only in production.

How to configure

There are 3 ways to configure your environment. The first way is adding the lines below in your web.xml. As example, you can configure the environment name as PRODUCTION:

<context-param>
    <param-name>br.com.caelum.vraptor.environment</param-name>
    <param-value>PRODUCTION</param-value>
</context-param>

The second way is adding a JVM property. For this you can start your Application Server or Servlet Container with this JVM parameter:

-Dbr.com.caelum.vraptor.environment=PRODUCTION

And the third option is setting an environment variable under your Operating System, simple adding the VRAPTOR_ENV variable.

Windows example:

set VRAPTOR_ENV=PRODUCTION

Unix example:

export VRAPTOR_ENV=PRODUCTION

Note: The environment variable of Operating System have more priority than JVM properties, that have more priority than web.xml configuration. So, as example, if your application uses both web.xml and JVM properties, the configuration over web.xml will ignored.

Setting an environment properties

You only need to create a properties file with the name of your environment in your classpath. As example, to set the properties for PRODUCTION environment you only need to create a file called production.properties like this:

test_environment=false
email=production.mail@mail.com

If you have a common properties for other environments you can create a file called environment.properties with these common properties. So VRaptor will ask for properties first in the environment file, and if not found, will ask in the environment.properties file.

You can also override properties using System Properties. Properties defined by System Properties will override any other definitions. Note: You can only use System Properties to override existing properties in property files and not to define a new one.

Considering that you have the environment.properties below: ~~~ #!properties my.prop hello ~~~

You can override the existing my.prop with a System Property like this: ~~~ #!java System.setProperty(“my.prop”, “bye”); environment.get(“my.prop”); //bye ~~~

If the key doesn’t exists in properties file, get method will throw a NoSuchElementException.

Getting environment properties in your code

There are two methods to get the properties: get and getOrDefault. The first method returns the property value if the value exists, or an MissingResourceException if not found. And with getOrDefault you can return a default value if the key is not found. Take a look in the code below:

@Controller
public class MyController {

    private final Environment environment;

    private final MailSender sender;

    /**
     * @deprecated CDI eyes only
     */
    protected MyController(){
        this(null, null);
    }

    @Inject
    public MyController(Environment environment, MailSender sender) {
        this.environment = environment;
        this.sender = sender;
    }

    public void sendMail(String email) {
        if(environment.isDevelopment()) {
            sender.sendMailTo(environment.get("email"));
        } else {
            sender.sendMailTo(email);
        }
    }
}

In the code above, environment.get("email") we will get the property email. But if this property is not always present, we can use the getOrDefault method to return a default value.

public void sendMail(String email) {
        if(environment.isDevelopment()) {
            sender.sendMailTo(environment.getOrDefault("email"), "noreply@vraptor.org");
        } else {
            sender.sendMailTo(email);
        }
}

Getting environment properties in your JSP

<c:if test="${environment.isTest()}">
    <p>You are now in the test environment. Your actions here will not affect the system.</p>
</c:if>

Send an e-mail to: ${environment.get('email')}

Accessing configuration files according to the environment

If you need to access a file in a different setting for your libraries according to your environment, you can also use the environemnt. Just put, for example, your hibernate.cfg.xml under directories located with the name of your environment: development and production (for example). Environment.getResource (...) returns the resource according to your current environment:

cfg = new AnnotationConfiguration();
cfg.configure(environment.getResource("/hibernate.cfg.xml"));

To keep compatibility with applications that don’t not environment, if the file isn’t found in the directory with the name of the environment, it will be loaded from classpath.

Injecting the value of your configuration programmatically

You can also inject your settings programmatically using @Property annotation, like:

@Controller
public class MyController {

    @Inject
    @Property("email")
    private String email;

    public void sendMail(String email) {
        sender.sendMailTo(email);
    }
}

If your environment is DEVELOPMENT, the value for key email will be loaded using development.properties. And if your environment is PRODUCTION the value will be loaded from production.properties. This feature allow you to keep away from conditional statements like: if (environment.isDevelopment ()) {...} in your code.

And if the field name is the same from the key, you can use only the @Property annotation without define a value, like this:

@Controller
public class MyController {

    @Inject
    @Property
    private String email;

    public void sendMail(String email) {
        sender.sendMailTo(email);
    }
}

You can also set a default value for this property:

@Inject
@Property(defaultValue = "config.properties")
private String fileName;