1. 2016-03-07 - Use Dropwizard Metrics with CDI in Java EE; Tags: Use Dropwizard Metrics with CDI in Java EE
    Loading...

    Use Dropwizard Metrics with CDI in Java EE

    Java EE provides with CDI (Contexts and Dependency Injection) a powerful way to write loose coupled code. Dropwizard Metrics is a wonderful library to collect metrics about your application. This post shows how to integrate Dropwizard Metrics with CDI into an Java EE application.

    Create qualifier for type Metric

    /**
    * Qualifier used to disambiguate metrics based on their registered name.
    */
    @Retention(RUNTIME)
    @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
    @Qualifier
    public @interface Metric {
        /**
         * Name of the metric, as registered in {@link com.codahale.metrics.MetricRegistry}.
         * @return the metric name
         */
        String value();
    }
    

    The class with the central MetricRegistry, eligible for injection

    /**
     * Producer for Dropwizard Metrics registry.
     */
    @ApplicationScoped
    public class Metrics {
        private Slf4jReporter metricsReporter;
        private final MetricRegistry metricRegistry = new MetricRegistry();
        @Produces
        @Singleton
        public MetricRegistry getRegistry() {
            return metricRegistry;
        }
        @PostConstruct
        public void postConstruct() {
            metricsReporter = Slf4jReporter.forRegistry(metricRegistry)
                    .outputTo(LoggerFactory.getLogger("metrics"))
                    .convertRatesTo(SECONDS)
                    .build();
            metricsReporter.start(30, SECONDS);
        }
        @PreDestroy
        public void preDestroy() {
            metricsReporter.stop();
        }
        /**
         * Executes a {@link Runnable} in the context of the given timer.
         * @param timer the timer
         * @param runnable the action to run
         */
        public static void timed(Timer timer, Runnable runnable) {
            try (Timer.Context ignored = timer.time()) {
                runnable.run();
            }
        }
        /**
         * Executes a {@link Supplier} in the context of the given timer.
         * @param timer the timer
         * @param supplier the action to run
         */
        public static <T> T timed(Timer timer, Supplier<T> supplier) {
            try (Timer.Context ignored = timer.time()) {
                return supplier.get();
            }
        }
    }
    

    Create producer that automatically registers the metric to the central registry

    /**
     CDI producers for metrics
     */
    public class BatchMetrics {
        public static final String DELIVERY_SIZE = "delivery.size";
        @Inject
        private MetricRegistry metricRegistry;
        @Produces
        @Metric(DELIVERY_SIZE)
        Histogram deliverySize() {
            return metricRegistry.histogram(DELIVERY_SIZE);
        }
    //..
    }
    
  2. 2015-11-09 - Restricting the bean types of a bean in CDI; Tags: Restricting the bean types of a bean in CDI
    Loading...

    Restricting the bean types of a bean in CDI

    The bean types of a bean may be restricted by annotating the bean class or producer method or field with the annotation @javax.enterprise.inject.Typed.

    We have 2 bean implementations:

    public class CnfgParamMapper {}
    

    Second bean extends from first bean

    public class CnfgParamSetMapper extends CnfgParamMapper {}
    

    Now you want to inject either one or both beans, you will stumble over an exception.

    @RunWith(CdiRunner.class)
    public class CnfgParamMapperTest {
        @Inject private CnfgParamMapper cnfgParamMapper;
        @Inject private CnfgParamSetMapper cnfgParamSetMapper;
        //..
    }
    

    The exception more in detail

    org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type CnfgParamMapper with qualifiers @Default
      at injection point [UnbackedAnnotatedField] @Inject private net.cinhtau.parser.mapping.element.CnfgParamMapperTest.cnfgParamMapper
      at net.cinhtau.parser.mapping.element.CnfgParamMapperTest.cnfgParamMapper(CnfgParamMapperTest.java:0)
      Possible dependencies:
      - Managed Bean [class net.cinhtau.parser.mapping.element.CnfgParamMapper] with qualifiers [@Any @Default],
      - Managed Bean [class net.cinhtau.parser.mapping.element.CnfgParamSetMapper] with qualifiers [@Any @Default]
    

    Since CnfgParamSetMapper extends from CnfgParamMapper, it is also eligible for injection. The type is resolved to:

    • CnfgParamMapperCnfgParamMapper.class, Object.class
    • CnfgParamSetMapperCnfgParamMapper.class, CnfgParamSetMapper.class, Object.class

    By injecting CnfgParamMapper, weld can’t distinguish which one is the correct one, so it is ambiguous.

    Solution

    To avoid the ambigous situation above, we restrict the types by explicitly defining the type for injection on the bean implementations. first bean

    @Typed(value = { CnfgParamMapper.class })
    public class CnfgParamMapper
    

    second bean

    @Typed(value = { CnfgParamSetMapper.class })
    public class CnfgParamSetMapper extends CnfgParamMapper {}
    

    As we only define the CnfgParamSetMapper.class, we explicitly removed the superclass (CnfgParamMapper.class) from the bean type resolution.

  3. 2015-11-02 - beans.xml in Java EE 7; Tags: beans.xml in Java EE 7
    Loading...

    beans.xml in Java EE 7

    If you are familiar with CDI (Contexts and Dependency Injection) you know that in Java EE 6 you need a beans.xml in META-INF or WEB-INF the module for getting the CDI magic to work. Basically it is needed for the beans discovery. Everyone has now and then maybe forgot the beans.xml. With Java EE 7 it has changed.

    CDI is now enabled by default. This means that there’s no need to explicitly add a beans.xml to enable DI any more. Java EE 7 offers finer grained control in the beans discovery. Read more Default CDI enablement in Java EE 7.

    cdi
  4. 2015-10-20 - Test depths within Java EE; Tags: Test depths within Java EE
    Loading...

    Test depths within Java EE

    TDD and BDD is a crucial discipline to write good and robust applications. Testing within the Java EE may cover several test depths. This post is only a short overview of possible involved products.

    Testing - test depth Local Testing

    • In the local testing part or Java SE Testing, we test against a single class.
    • Therefore the test execution is fast.
    • Preferred tools are JUnit (or TestNG), Mocking frameworks like Mockito

    Multi-Unit Testing

    • This test stage test against a service or a dedicated environment like CDI provider or JPA DB
    • For CDI tests: CDI-Unit, Apache DeltaSpike
    • Tests in CDI involves correct setup and wiring
    • For JPA tests: Testing against in-memory databases
    • Tests in JPA involves proper setup and logical queries correctness
    • since tests are executed against an environment, they need more time to be executed

    Integration Testing

    • In this test stage, you may test the component, subsystem or the whole application
    • Arquilian allows in-container testing with JBoss and other Java EE vendors
    • Apache OpenEJB can be used to start test against the whole Java EE Stack
    • Since you are testing against a defined target environment, it takes more time to test.
  5. 2015-08-14 - CDI definition hell; Tags: CDI definition hell
    Loading...

    CDI definition hell

    As I had to give a training about Contexts and Dependency Injection for the Java EE Platform (CDI), I made a small graphic with Lucidchart about CDI.