Giter VIP home page Giter VIP logo

dropwizard-petite's Introduction

Status

CircleCI Coverage Status Codacy Badge Download Javadoc Dependency Status

dropwizard-petite

This library provides an integration for the awesome Jodd Petite and dropwizard. It provides a light weight dependency injection, similarly to Spring but with a much smaller footprint and better error messages.

It also comes with an optional implementation (MonitoredPetiteContainer) that adds metrics to PetiteContainer, so you can monitor the cost of running Petite in your application. By default it's disabled and works exactly as if you implemented it yourself.

Jodd Petite by default will make your beans singleton, which is perfect for most of DAOs and resource classes.

Supported versions:

Dropwizard-petite Dropwizard Jodd Petite
- 0.9.X 0.0.1
- 1.X.X 1.0.0
- 1.1.x 1.1.4
1.3.8 1.3.8 5.0.6

Maven

The library is available at the maven central, so just add dependency to pom.xml:

<dependencies>
  <dependency>
    <groupId>com.github.mtakaki</groupId>
    <artifactId>dropwizard-petite</artifactId>
    <version>1.3.8</version>
  </dependency>
</dependencies>

How to use it

Bundle

public class TestApplication extends Application<TestConfiguration> {
    // Adding hibernate just to show how to register the SessionFactory.
    private final HibernateBundle<TestConfiguration> hibernate = new HibernateBundle<TestConfiguration>(
            TestEntity.class) {
        @Override
        public DataSourceFactory getDataSourceFactory(
                final TestConfiguration configuration) {
            return configuration.getDatabase();
        }
    };

    // This is the Jodd Petite bundle.
    private final PetiteBundle<TestConfiguration> petite = new PetiteBundle<TestConfiguration>() {
        @Override
        protected PetiteConfiguration getConfiguration(final TestConfiguration configuration) {
            return configuration.getPetite();
        }
    };

    @Override
    public void initialize(final Bootstrap<TestConfiguration> bootstrap) {
        bootstrap.addBundle(this.hibernate);
        bootstrap.addBundle(this.petite);
    }

    @Override
    public void run(final TestConfiguration configuration, final Environment environment)
            throws Exception {
        // Registering the SessionFactory to the container because SessionFactory is not annotated
        // with @PetiteBean.
        this.petite.getPetiteContainer().addBean(SessionFactory.class.getName(),
                this.hibernate.getSessionFactory());

        // Here we're asking the Petite container to get/build the resource.
        environment.jersey().register(this.petite.getPetiteContainer().getBean(TestResource.class));
    }
}

Beans

To expose your class as a bean you will need to annotate it with @PetiteBean and the constructor with @PetiteInject, although the latter is optional as Petite can figure it out automatically. Commonly you would annotate your DAO and Resource classes, like this:

@PetiteBean
public class TestDAO extends AbstractDAO<Test> {
    @PetiteInject
    public TestDAO(SessionFactory sessionFactory) {
        super(sessionFactory);
    }
}

The DAO class depends on having the SessionFactory registered in the container, otherwise it won't find it when calling the constructor.

The Resource class:

@PetiteBean
public class TestResource {
    private final TestEntityDAO dao;
    
    @PetiteInject
    public TestResource(TestEntityDAO dao) {
        this.dao = dao;
    }
}

Configuration

The bundle comes with PetiteConfiguration, so your configuration will look like this:

public class TestConfiguration extends Configuration {
    private final PetiteConfiguration petite = new PetiteConfiguration();
    
    public PetiteConfiguration getPetite() {
        return this.petite;
    }
}

And the YAML will look like this:

petite:
  useFullTypeNames: true
  automagicConfigurator: true
  registerSelf: true
  useMetrics: true
  • useFullTypeNames, will make the container use the full class name, rather than just the getSimpleName(). This is very useful to avoid class names collision.
  • automagicConfigurator, will make the container automatically look for beans in the class path. If this is not configured, you will need to manually register your beans.
  • registerSelf, will register the container into itself.
  • useMetrics, will use the MonitoredPetiteContainer and will push metrics for the methods getBean() and addBean().

Metrics

These metrics will show up if you setup the useMetrics settings to true (it's default to false). This will show up exactly the overhead of using Jodd Petite.

{
"timers" : {
    "com.github.mtakaki.dropwizard.petite.MonitoredPetiteContainer.addBean" : {
      "count" : 2,
      "max" : 0.006725265,
      "mean" : 0.003824707,
      "min" : 9.241490000000001E-4,
      "p50" : 0.006725265,
      "p75" : 0.006725265,
      "p95" : 0.006725265,
      "p98" : 0.006725265,
      "p99" : 0.006725265,
      "p999" : 0.006725265,
      "stddev" : 0.002900558,
      "m15_rate" : 0.4,
      "m1_rate" : 0.4,
      "m5_rate" : 0.4,
      "mean_rate" : 0.2675745788220869,
      "duration_units" : "seconds",
      "rate_units" : "calls/second"
    },
    "com.github.mtakaki.dropwizard.petite.MonitoredPetiteContainer.getBean" : {
      "count" : 2,
      "max" : 0.00296589,
      "mean" : 0.0029420970000000003,
      "min" : 0.002918304,
      "p50" : 0.00296589,
      "p75" : 0.00296589,
      "p95" : 0.00296589,
      "p98" : 0.00296589,
      "p99" : 0.00296589,
      "p999" : 0.00296589,
      "stddev" : 2.3793E-5,
      "m15_rate" : 0.4,
      "m1_rate" : 0.4,
      "m5_rate" : 0.4,
      "mean_rate" : 0.26755860731761477,
      "duration_units" : "seconds",
      "rate_units" : "calls/second"
    },
    "com.github.mtakaki.dropwizard.petite.PetiteConfiguration.automagicConfigurator" : {
      "count" : 1,
      "max" : 1.683990942,
      "mean" : 1.683990942,
      "min" : 1.683990942,
      "p50" : 1.683990942,
      "p75" : 1.683990942,
      "p95" : 1.683990942,
      "p98" : 1.683990942,
      "p99" : 1.683990942,
      "p999" : 1.683990942,
      "stddev" : 0.0,
      "m15_rate" : 0.2,
      "m1_rate" : 0.2,
      "m5_rate" : 0.2,
      "mean_rate" : 0.13377928037494183,
      "duration_units" : "seconds",
      "rate_units" : "calls/second"
    }
}

Debugging errors

Null pointer exception when registering resource

If you're getting an NPE when registering your resource, like this:

Exception in thread "main" java.lang.NullPointerException
	at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:210)
	at io.dropwizard.jersey.setup.JerseyEnvironment.register(JerseyEnvironment.java:37)
	at com.github.mtakaki.test.TestApplication.run(TestApplication.java:90)
	at com.github.mtakaki.test.TestApplication.run(TestApplication.java:1)
	at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:40)
	at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:77)
	at io.dropwizard.cli.Cli.run(Cli.java:70)
	at io.dropwizard.Application.run(Application.java:80)
	at com.github.mtakaki.test.TestApplication.main(TestApplication.java:34)

It means the container could not find your bean. It means that your bean was not registered.

Solutions:

  • Set automagicConfigurator: true in your configuration file.
  • Manually register the bean into your PetiteContainer.

Wiring exception

If your application fails to initialize due to a PetiteException and it throws this stack trace:

Exception in thread "main" jodd.petite.PetiteException: Wiring constructor failed. References 'null,sessionFactory,org.hibernate.SessionFactory' not found for constructor: public com.github.mtakaki.test.database.TestDAO(org.hibernate.SessionFactory)
	at jodd.petite.PetiteContainer.newBeanInstance(PetiteContainer.java:90)
	at jodd.petite.PetiteContainer.getBean(PetiteContainer.java:368)
	at jodd.petite.PetiteContainer.getBean(PetiteContainer.java:325)
	at jodd.petite.PetiteContainer.newBeanInstance(PetiteContainer.java:87)
	at jodd.petite.PetiteContainer.getBean(PetiteContainer.java:368)
	at jodd.petite.PetiteContainer.getBean(PetiteContainer.java:314)
	at com.github.mtakaki.dropwizard.petite.MonitoredPetiteContainer.getBean(MonitoredPetiteContainer.java:29)
	at jodd.petite.PetiteContainer.getBean(PetiteContainer.java:302)
	at com.github.mtakaki.dropwizard.petite.MonitoredPetiteContainer.getBean(MonitoredPetiteContainer.java:22)
	at com.github.mtakaki.test.TestApplication.run(TestApplication.java:88)
	at com.github.mtakaki.test.TestApplication.run(TestApplication.java:1)
	at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:40)
	at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:77)
	at io.dropwizard.cli.Cli.run(Cli.java:70)
	at io.dropwizard.Application.run(Application.java:80)
	at com.github.mtakaki.test.TestApplication.main(TestApplication.java:32)

It means the SessionFactory has not been added to the container. As the stack trace shows, it tried calling a constructor that receives a SessionFactory but it could not find the bean to call it.

Solution:

  • Register the SessionFactory. SessionFactory is not part of your project, so you cannot annotate it with @PetiteBean. The solution is to manually add the bean to the container so it can be found when auto-wiring your beans:
@Override
public void run(final TestConfiguration configuration,
        final Environment environment) throws Exception {
    final PetiteContainer petiteContainer = this.petite.getPetiteContainer();
    petiteContainer.addBean(SessionFactory.class.getName(), this.hibernate.getSessionFactory());
}

dropwizard-petite's People

Contributors

mtakaki avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Forkers

nicolasdichiara

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.