Tag Archives: configuration

CDI: replace the configuration by a register pattern


CDI doesn’t really have a configuration file. Of course the beans.xml is used to activate few features like interceptors but you can’t register a bean in it, can’t add a qualifier on a bean etc…

When it comes to writing a CDI library the question of the configuration hits you pretty quickly. Let see how to solve it with a not very complicated pattern making users life really nicer.

Continue reading

Align TomEE and DeltaSpike ciphering configuration


When you develop an application relying on a container for its awesome features you often hit the fact you use several code bases to do the same thing. In the context of this post it will be the ciphering of the passwords in the configuration:

  • TomEE does it using PasswordCipher API
  • DeltaSpike does it using ConfigFilter API
  • So finally you end up having to maintain two ciphering solutions which makes hard to production teams to maintain the configuration without developpers.

    Continue reading

DeltaSpike configuration: read where you want and decrypt passwords


DeltaSpike configuration: read where you want and decrypt passwords

DeltaSpike configuration is a very elegant configuration solution for CDI.

However to make it fitting your application you often need to integrate it:

  • to read the configuration from the source/location you desire
  • to use a custom algorithm to decrypt passwords or sensitive data

Read your own configuration file

There are generally three cases to add a custom configuration file:

  • respect a company convention
  • read it from outside the application (in ${tomee.base}/conf for instance ;))
  • read a custom format (yaml, xml, …)

In this post we will tackle the second one since mixing the last two solves generally the first one and the last one is mainly the same solution with some specific conversion logic I don’t want to enter in for this post.

So our goal will be to read the configuration from ${catalina.base}/conf/my-app.properties and add it in deltaspike properties.

To do so we just need deltaspike core:

<dependency>
  <groupId>org.apache.deltaspike.core</groupId>
  <artifactId>deltaspike-core-api</artifactId>
  <version>${deltaspike.version}</version>
</dependency>
<dependency>
  <groupId>org.apache.deltaspike.core</groupId>
  <artifactId>deltaspike-core-impl</artifactId>
  <version>${deltaspike.version}</version>
</dependency>

Then we need to implement a custom org.apache.deltaspike.core.spi.config.ConfigSource reading ${catalina.base} from the corresponding system properties (our implementation will have a fallback on openejb.base property for openejb embedded tests):

import org.apache.deltaspike.core.impl.config.PropertiesConfigSource;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

// uses ${base}/conf/my-app.properties as source
public class MyConfigSource extends PropertiesConfigSource {
    public MyConfigSource() {
        super(loadProperties());
    }

    public String getConfigName() {
        return "MyAppConfig";
    }

    private static Properties loadProperties() {
        return new Properties() {{
            final File config = new File(
                System.getProperty("catalina.base", System.getProperty("openejb.base", "")),
                "conf/my-app.properties");
            if (config.isFile()) {
                try (final InputStream is = new BufferedInputStream(new FileInputStream(config))) {
                    load(is);
                } catch (final IOException e) {
                    throw new IllegalArgumentException(e);
                }
            }
        }};
    }
}

Then to “activate” it just create a META-INF/services/org.apache.deltaspike.core.spi.config.ConfigSource containing our qualified class name.

Decrypt passwords with your own algorithm

To decrypt password DeltaSpike uses org.apache.deltaspike.core.spi.config.ConfigFilter implementations. It has two methods:

  • filterValue: actual decryption
  • filterValueForLog: decryption for logging, in general I just log “xxxxxx” if my filter handles the value

For this post the decryption will just reverse the value but a real implementation can use any ciphering considered secured in your environment:

import org.apache.deltaspike.core.spi.config.ConfigFilter;

public class MyConfigFilter implements ConfigFilter {
    @Override
    public String filterValue(final String key, final String value) {
        return isEncrypted(key) ? decrypt(value) : value;
    }

    @Override // filter passwords and secrets in logs
    public String filterValueForLog(final String key, final String value) {
        return isEncrypted(key) ? "xxxxxx" : value;
    }

    // for the sample just "reverse" the string but in real life use some encryption
    private String decrypt(final String value) {
        return new StringBuilder(value).reverse().toString();
    }

    private boolean isEncrypted(final String key) {
        return key.contains("password") || key.contains("secret");
    }
}

As for ConfigSource and since this classes are used before CDI is started to configure DeltaSpike itself don’t forget to register the filter adding the fully qualified name in META-INF/services/org.apache.deltaspike.core.spi.config.ConfigFilter.

Now if you set for instance in your configuration:

my.password = tset

And get my.password injected:

@Inject
@ConfigProperty(name = "my.password")
private String pwd;

Then pwd value will be test :).

Conclusion

The code of this post can be found there: https://github.com/rmannibucau/deltaspike-config-example.

The interesting part is to understand deltaspike can be integrated with all kind of configuration and environment which is the main feature of a configuration API. Then you still get it integrated with CDI for free thanks to DeltaSpike @ConfigProperty which makes your application simple and decoupled from your actual configuration system.

TomEE, @WebServiceRef and configuration


TomEE+ integrates JAX-WS thanks to CXF implementation. It allows you
to develop Pojo or EJB webservices but TomEE takes care to keep all CXF features.

This means you can use openejb-jar.xml to configure your webservice.

As a quick reminder the configuration (openejb-jar.xml) looks like the following one for an EJB:

<?xml version="1.0" encoding="UTF-8"?>
<openejb-jar xmlns="http://www.openejb.org/openejb-jar/1.1">
  <ejb-deployment ejb-name="CalculatorBean"> <!-- configure the bean, values are in resources.xml -->
    <properties>
      cxf.jaxws.in-interceptors = serviceIdInResourcesXml,com.foo.FullyQualifiedInterceptor
      cxf.jaxws.out-interceptors = abc
      cxf.jaxws.in-fault-interceptors = def
      cxf.jaxws.out-fault-interceptors = hgi
      cxf.jaxws.features = jkl
      cxf.jaxws.debug = true
    </properties>
  </ejb-deployment>
</openejb-jar>

For a Pojo webservice it is the same but using pojo-deployment instead of ejb-deployment.

TomEE also has (historically) some specific integration with wss4j but with
the previous configuration it is pretty useless now. Only thing to know
about wss4j is openejb provides WSS4JInInterceptorFactory factory
to ease initialization of WSS4JInInterceptor interceptor (because it has
two constructors with a single parameter and it can be ambiguous in some cases).

Finally to configure wss4j you can do a resources.xml like:

<?xml version="1.0"?>
<resources>
  <Service id="wss4jin" class-name="org.apache.openejb.server.cxf.config.WSS4JInInterceptorFactory" factory-name="create">
    passwordType = PasswordDigest
    action = UsernameToken
    passwordCallbackClass = com.foo.MyCallbackHandler
  </Service>
</resources>

And an openejb-jar.xml like:

<?xml version="1.0" encoding="UTF-8"?>
<openejb-jar xmlns="http://www.openejb.org/openejb-jar/1.1">
  <ejb-deployment ejb-name="CalculatorBean"> <!-- configure the bean, values are in resources.xml -->
    <properties>
      cxf.jaxws.in-interceptors = org.apache.cxf.binding.soap.saaj.SAAJInInterceptor,wss4jin,org.apache.openejb.server.cxf.WSSPassThroughInterceptor
    </properties>
  </ejb-deployment>
</openejb-jar>

This is great but it has a pitfall: it is only for the server side!

This is the reason it was recently enhanced (will be available in next 1.7.2 and 2.x versions) to
support almost the same configuration for clients.

In JavaEE clients are done thanks to @WebServiceRef. TomEE already optimizes them
using local invocation when the service is deployed int the same instance and doesn’t need
remote invocation (ie it has no webservice handler) but if you needed to customize
the client for remote case (ading security, adding logging, …) you needed
to cast it thanks to CXF APIs and programmtically customize the port.

When @WebServiceRef is used to get injected a port (ie a real client) you can now simply
configure CXF client like on server side.

However client doesn’t match pojo-deployment or ejb-deployment. That is why it uses
application.properties (in WEB-INF folder). Syntax is exactly the same but in properties
format. Prefix is “cxf.jaxws.client.” or “cxf.jaxws.client.{namespace}PortName”.
Take care first one is global (ie shared for all clients) and second one is specific to a port.

Like explaining such a configuration would not be that efficient here a sample:

cxf.jaxws.client.{http://cxf.server.openejb.apache.org/}MyWebservicePort.out-interceptors = wss4jout

wss4jout = new://Service?class-name=org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor&constructor=properties
wss4jout.properties = $outProperties

# using a pass-through class to configure more easily properties
outProperties = new://Service?class-name=org.apache.openejb.config.sys.MapFactory
outProperties.action = UsernameToken
outProperties.passwordType = PasswordDigest
outProperties.passwordCallbackClass = com.foo.MyClientCallbackHandler

Bonus: a Service (or a subclass of Service) can be injected as well. Customization doesn’t go as far as for the port but you
can set WSFeatures using the key: cxf.jaxws.client.xxx.wsFeatures and the value has to be a list of id or fully qualified name
of WSFeatures.

On recent version using resources.xml for Service should be possible as well, mainly a taste
question :).

TomEE and JAXRS provider configuration depending on environment


TomEE supports “environment integration” through several solutions (altdd support, external configuration using conf/system.properties etc….). But how to configure a JAXRS provider depending the environment?

First why should I need it? Suppose you configured a JSON provider, quite common for a JAX-RS application no? You want your application to be efficient in production so you use “flat” JSON but in dev you surely prefer to get formatted (“pretty”) JSON to keep it readable.

How to do it with TomEE?

Continue reading