The runtime properties

You may want to add some flexibility to your application by changing a property without needing to recompile the code or restarting the server. This way you can distribute the same WAR file of your web application to different places. You can think at the following situations:

The properties for your APIs are defined in the runtime properties file often named xins.properties. This file location is passed to the application server with the system property org.xins.server.config.

To start the WAR file using the XINS servlet container, just execute xins -Dorg.xins.server.config=xins.properties run-myproject. You can also set the location of the xins.properties in the build.properties and then execute xins run-myproject.

Note

If you want to run the example in tomcat, you need to add in the file tomcat\conf\catalina.properties the line org.xins.server.config=c:\\Program\ Files\\xins\\demo\\xins.properties.

Example of runtime properties file:

#_____________________________________________________________________________
# General XINS properties

# Check configuration file every 60 seconds
org.xins.server.config.reload=60

# Access rules
org.xins.server.acl=allow 127.0.0.1 *;

# Logging properties
org.xins.logdoc.locale=en_US

An example is also provided in the demo\xins.properties file.

The properties

Some properties defined in this file are already interpreted by the system:

Table 2. xins.properties runtime properties

Property nameRequiredDescriptionExample
org.xins.server.config.reloadno, defaults to 60.Interval in seconds for check the xins.properties file for any changes.org.xins.server.config.reload=60
org.xins.server.aclno, defaults to localhost.Access rules for the functionsorg.xins.server.acl=allow 127.0.0.1 *; \ allow 192.168.0.0/24 MyFunction
org.xins.server.acl.<api name>noAccess rules for the functions of the specified API. The specified rules are executed before the generic one.org.xins.server.acl.myproject=allow 127.0.0.1 *; \ deny 192.168.0.0/24 MyFunction
org.xins.server.config.includenoA comma separated list of runtime property files to include. The files should use relative paths.org.xins.server.config.include=../default-xins.properties
org.xins.logdoc.localeno, defaults to en_US.The locale to be used for the logging messages.org.xins.logdoc.locale=en_US
org.xins.server.jmxno, false by default.Enables the management of the API using JMX (Java Management eXtension).org.xins.server.jmx=true
org.xins.server.contextID.filterno, all types of context ID are accepted by default.The regular expression pattern for the expected format of the context ID. If the context ID is invalid, a new one will be generated.org.xins.server.contextID.filter=[a-zA-Z]{5}
org.xins.logdoc.stackTraceAtMessageLevelno, defaults to false meaning that the stack traces are logged at DEBUG level.Flag indicating that the exception stack trace should be logged at the same level as the message.org.xins.logdoc.stackTraceAtMessageLevel=true
log4j.*no, defaults to console.Logging properties used to adapt the debug level, formatting or output to your needs.log4j.rootLogger=DEBUG, console
log4j.<api name>.rootLoggerno, defaults to log4j.rootLogger.Root logger for the specified API.log4j.myproject.rootLogger=INFO, logfile_myproject

Getting properties value

Now we will adapt the xins.properties for the MyFunction implementation by adding the following lines:

# Salutation message for the person
salutation=Hello

We now need to change the implementation to read and use the property. Note that the property should be able to be changed at runtime. Add the following code to MyFunctionImpl.java

import org.xins.common.collections.MissingRequiredPropertyException;
import org.xins.common.collections.InvalidPropertyValueException;
import org.xins.common.collections.PropertyReader;
import org.xins.common.manageable.BootstrapException;
import org.xins.common.manageable.InitializationException;

...
   /**
    * The salutation message.
    */
   private String _salutation;

   protected void initImpl(PropertyReader properties)
   throws MissingRequiredPropertyException,
          InvalidPropertyValueException,
          InitializationException {

      // Get the salutation
      _salutation = properties.get("salutation");
      if (_salutation == null || _salutation.trim().equals("")) {
         throw new MissingRequiredPropertyException("salutation");
      }
      // Here you can also chack the value and throw an
      // InvalidPropertyValueException if needed
   }

   public final Result call(Request request) throws Throwable {
...
      result.setMessage(_salutation + " " + nomination + " " +
                        request.getPersonLastName());
      return result;
   }

Now recompile your code, restart the server, execute the function, change the value in xins.properties to Hi, wait for the server to reload the properties file and execute the function again.

The API class defines a deinitImpl() method. This method is used to release resources when you stop the API.

Note

When the xins.properties file has changed, only the initImpl() method is invoked. The deinitImpl() is called only when you stop the servlet container.

The API class has a bootstrapImpl2(PropertyReader buildSettings) method that is called the API is started. The buildSettings passed as parameters are the properties stored in the web.xml file included in the deployment war file.

The API class has a reinitializeImpl() method. This method can be invoked in your implementation to ask the framework to reinitialize the API.

Defining properties

XINS 1.3.0 includes a new system that allows to define runtime properties that you will use in your API in the impl.xml file. In this file you define the name of the property, its description, its type and whether is property is required or optional. The value of the property still needs to be defined in the xins.properties file.

Example:

<impl>
  <runtime-properties>
    <property name="myproject.eurodollar.rate" type="_float32" required="true">
      <description>The price in dollars of 1 euro.</description>
    </property>
  </runtime-properties>
</impl>

Now when the specification documentation is generated, a new page is available containing the list of the runtimes properties used by the API along with their description, their type and whether the property is required or optional. This page makes it easier to deploy an API with the correct runtime properties set.

Another advantage of defining the properties this way is that you don't need to implement the initImpl method to retreive the property values. A class is generated that checks and retreives the properties. If the value of a property is incorrect or a required property is missing then the API will fail with a description of the problem. The getAPI().getProperties() method can also be called from the initImpl method of your function, if you want for example initialize another object based on a runtime property.

Example on how to use the generated class:

   // No imports needed, no initImpl method needed

   public final Result call(Request request) throws Throwable {
      SuccessfulResult result = new SuccessfulResult();
      result.setPriceInEuro(request.getPriceInDollar() /
         ((RuntimeProperties) getAPI().getProperties()).getMyprojectEurodollarRate());
      return result;
   }

If the property was optional, a java.lang.Float object would have been returned.