/java/

Using @Produces Annotation.

2015-07-07 23:28:13

Assume we have interface:

package pl.btbw.service;
public interface BirdService {
}

with two implementation

SiskinService.java

package pl.btbw.service;

public class SiskinService implements BirdService {

    @Override
    public String toString() {
        return "String form SiskinService{}";
    }
}

SparrowService.java

package pl.btbw.service;

public class SparrowService implements BirdService {

    @Override
    public String toString() {
        return "String form SparrowService";
    }
}

and now we wont to inform CDI which Implementation of BirdService inject when we type something like this in our controller:

package pl.btbw;

import pl.btbw.service.BirdService;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/")
public class AppCtrl {

    @Inject
    private BirdService birdService;

    @GET
    public String getTestString() {

        return "test:" + birdService.toString();
    }

}

btw. on this stage, deploying throw exception

java.lang.Exception: ....
[UnbackedAnnotatedField].....
Possible dependencies: 
  - Managed Bean [class pl.btbw.service.SiskinService] with qualifiers [@Any @Default],
  - Managed Bean [class pl.btbw.service.SparrowService] with qualifiers [@Any @Default]
....

we can fix it!

you have to create enum:

package pl.btbw.factory;

public enum BirdEnum {

    SPARROW, SISKIN

}

next, custom annotation

package pl.btbw.factory;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD})
public @interface BirdInject {

    BirdEnum value();
}

and finally factory

package pl.btbw.factory;

import pl.btbw.service.BirdService;
import pl.btbw.service.SiskinService;
import pl.btbw.service.SparrowService;

import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.Produces;
import java.io.Serializable;

@SessionScoped
public class BirdServiceFactory implements Serializable {

    private BirdEnum birdEnum;

    @Produces
    @BirdInject(BirdEnum.SPARROW)
    public BirdService getSparrowService() {
        return new SparrowService();
    }

    @Produces
    @BirdInject(BirdEnum.SISKIN)
    public BirdService getSiskinService() {
        return new SiskinService();
    }

}

that's all, now you can use customs annotation to inform CDI which implementation choose

package pl.btbw;

import pl.btbw.factory.BirdEnum;
import pl.btbw.factory.BirdInject;
import pl.btbw.service.BirdService;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/")
public class AppCtrl {

    @Inject
    @BirdInject(BirdEnum.SPARROW)
    private BirdService birdService;

    @GET
    public String getTestString() {

        return "test:" + birdService.toString();
    }

}

Github