1

I use java/jetty self-hosted server and jersey-2 for java RESTful api. Application has application.properties file with properties.

ConfigurationProperties class reads and loads properties file into java.util.Properties class.

Jetty server instantiation is done in the following way.

     // Create and register resources
    final ResourceConfig resourceConfig = new ApiServiceConfig()
            .register(new DependencyInjectionBinder());

    ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

    contextHandler.setContextPath("/mydomain/api");
    Server jettyServer = new Server(8585);
    jettyServer.setHandler(contextHandler);

    ServletHolder jerseyServlet = new ServletHolder(new ServletContainer(resourceConfig));
    contextHandler.addServlet(jerseyServlet, "/*");

    // Create web context. Can't use.
    //WebApplicationContext webContext = getWebApplicationContext();
    // Add web context to servlet event listener.
    //contextHandler.addEventListener(new ContextLoaderListener(webContext));

    try {
        jettyServer.start();
        jettyServer.join();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        jettyServer.destroy();
    }

I can't use Spring AnnotationConfigWebApplicationContext as it requires commons-logging dependency which doesn't work in java-8.

How can I register Properties with jetty/jersey context and how can I retrieve values later(eg.: context.getProperty("prop.name"))?

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
Maxim
  • 4,152
  • 8
  • 50
  • 77

1 Answers1

9

You could...

Just configure the Properties object as an injectable, and inject it into wherever you need it

final Properties props ...
resourceConfig.register(new AbstractBinder() {
    @Override
    protected void configure() {
        bind(props).to(Properties.class);
    }
});

@Path("config")
public class ConfigResource {

    @Inject
    private Properties properties;

}

You could...

Make the individual properties injectable, using an InjectionResolver and a custom annotation

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public static @interface Config {
    String value();
}

public class ConfigInjectionResolver implements InjectionResolver<Config> {

    private final Properties properties;
    public ConfigurationInjectionResolver(Properties properties) {
        this.properties = properties;
    }

    @Override
    public Object resolve(Injectee injectee, ServiceHandle<?> handle) {
        if (String.class == injectee.getRequiredType()) {
            Config annotation = injectee.getParent().getAnnotation(Config.class);
            if (annotation != null) {
                String prop = annotation.value();
                return properties.getProperty(prop);
            }
        }
        return null;
    }
    ...
}

final Properties props...
resourceConfig.register(new AbstractBinder(){
    @Override
    protected void configure() {
        bind(new ConfigInjectResolver(props))
                .to(new TypeLiteral<InjectionResolver<Config>>(){});
    }
});

Then just use it with the custom annotation

@Path("config")
public class ConfigResource {

    @Config(PROP_KEY)
    private String propValue;

    @GET
    public String getConfigProp() {
        return propValue;
    }
}

You could...

Use a small library that I made

<dependency>
    <groupId>com.github.psamsotha</groupId>
    <artifactId>jersey-properties</artifactId>
    <version>0.1.1</version>
<dependency>

resourceConfig.register(JerseyPropertiesFeature.class);
resourceConfig.property(JerseyPropertiesFeature.RESOURCE_PATH, "appication.properties");

@Path("test")
public class SomeResource {

    @Prop("some.prop")
    private String someFieldProp;

    private String someConstructorProp;

    public SomeResource(@Prop("some.prop") String someConstructorProp) {
        this.someConstructorProp = someConstructorProp;
    }

    @GET
    public String get(@Prop("some.prop") String someParamProp) {
        return someParamProp;
    }
}

You could...

Use Spring. I think the problem you are facing with using Java 8, is that you are using Spring 3.x. I don't think Java 8 is supported. I have had no problems using Jersey/Spring4 with java 8. If you are using the jersey-spring3 dependency, you need to exclude the spring3 dependencies, and add the spring 4. See the UPDATE in this post

See Also:

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Where should public static @interface Config { ... } sit? In it the same class, separate interface class? – Maxim Mar 31 '16 at 14:24
  • It doesn't need to be static. I was just testing it out and had it as an inner class when testing. If you want it in it's own file, it shouldn't (and can't) be static. Also the other two method in the InjectionResolver that you need to override, you can just return false for both of them – Paul Samsotha Mar 31 '16 at 14:26
  • In it's own file those annotations are not allowed. – Maxim Mar 31 '16 at 14:39
  • If it's in a single file, does it mean that ConfigInjectionResolver class is going to be an inner class? – Maxim Mar 31 '16 at 14:40
  • No. It should be in it's own file. All the classes I've shown should be in their own file – Paul Samsotha Mar 31 '16 at 14:41
  • I'll try with Spring4 – Maxim Mar 31 '16 at 14:43
  • It is, 2 days spent with no luck just to manage properties. Insane. – Maxim Mar 31 '16 at 14:48