Java : Builder Design Pattern - java

I have classes which has been autowired with all the attributes related to it. I need to return the object of these classes when a request for a particular class is received. A senior developer is suggesting to use the builder pattern. However the information I would be passing is just the request. I am confused can someone help.
Class DogDetailsProvider{
#Autowired
DogVendor dVendor;
#Autowired
DogOwner dOwner;
#Autowired
DogHealth dHealth;
}
Class CatDetailsProvider{
#Autowired
CatVendor cVendor;
#Autowired
CatOwner cOwner;
#Autowired
CatHealth cHealth;
}
Class ElephantDetailsProvider{
#Autowired
EleVendor eVendor;
#Autowired
EleOwner eOwner;
#Autowired
EleHealth eHealth;
}

I think that you probably need something like Service Locator Pattern. It helps decide which object you have to use depending on particular request. It reduces boilerplate code when you want to access your services.
At first you have to create interface with accessor methods to your vendor/owner/health classes:
public interface DetailsProvider {
Vendor getVendor();
Owner getOwner();
Health getHealth();
}
Your DogDetailsProvider, CatDetailsProvider, ElephantDetailsProvider have to implement that DetailsProvider interface. Also your vendor/owner/health classes have to have interface to keep inheritance mechanism.
Then you have to create service locator:
#Service
public class DetailsProviderLocator {
private DetailsProvider dogDetailsProvider;
private DetailsProvider catDetailsProvider;
private DetailsProvider elephantDetailsProvider;
#Autowired
public DetailsProviderLocator(
#Qualifier("DogDetailsProvider") DetailsProvider dogDetailsProvider,
#Qualifier("CatDetailsProvider") DetailsProvider catDetailsProvider,
#Qualifier("ElephantDetailsProvider") DetailsProvider elephantDetailsProvider) {
this.dogDetailsProvider = dogDetailsProvider;
this.catDetailsProvider = catDetailsProvider;
this.elephantDetailsProvider = elephantDetailsProvider;
}
DetailsProvider getDetailsProvider(Animal animal) {
switch(animal) {
case CAT : return catDetailsProvider;
case DOG : return dogDetailsProvider;
case ELEPHANT : return elephantDetailsProvider;
default : throw new IllegalArgumentException("Not allowed!");
}
}
}
public enum Animal {
CAT, DOG, ELEPHANT;
}
Now depending on enum (which can be anything, depends on your request) your service locator will return specific service. It is also easy to extend, because of inheritance you can create new services and just add new value to enum.

I need to return the object of these classes when a request for a particular class is received
This sounds like you need getter methods for objects such as dVendorin classes like DogDetailsProvider. You can either add boilerplate code for the getter methods or use lombok's #Getter.
Builder pattern is used to create objects by exposing setter methods in a builder class for each of the attributes of the object which needs to be built. Since you need to "get" and not "set" any data, using the Builder pattern would not help at all.

Related

How to Inject all subclasses of a specific class with no common interface?

Question:
In order to Inject all subclasses of a superclass with no common interface, I created an interface tightly-coupled to said superclass, that every "properly" written subclass is supposed to implement.
This works, but seems insane. Was there a better way?
A simple cast do not work, as the Instance holds only a proxy that do not resolves to any real subclass of the interface when called. This results in a ClassCastException.
Some context:
I was recently tasked to provide framework code for an application. In this application, several data transfer objects are mapping from and to service level POJOs, but their mappings are not always trivial. Dozer is used to do most of the work and to avoid boilerplate code.
In the specific cases requiring explicit mapping instructions, the current recommendation with Dozer is to use the API driven mapping. All the BeanMappingBuilder subclasses, defining the mappings, should be added to the Dozer mapper upon initialisation.
In order to keep all the work needed to add a new BeanMappingBuilder in one place, I came with a convoluted use of dependancy injection that will automatically add it to the Dozer mapper, despite it having no common interface, only a common superclass with the others.
Some code:
The interface:
#Local
public interface DtoBeanMappingBuilder {
BeanMappingBuilder get();
}
Subclass example:
#Stateless
public class SomeDtoMappingBuilder extends BeanMappingBuilder implements DtoBeanMappingBuilder {
#Override
public BeanMappingBuilder get() {
return this;
}
#Override
protected void configure() {
mapping(
// Some mapping...
);
}
}
Mapper with injection point:
#Singleton
#Startup
public class DtoBeanMapper {
private DozerBeanMapper innerMapper;
#Inject
#Any
private Instance<DtoBeanMappingBuilder> mappingBuilders;
public <D> D map(Object source, Class<D> destinationClass) {
return innerMapper.map(source, destinationClass);
}
#PostConstruct
private void init() {
innerMapper = new DozerBeanMapper();
mappingBuilders.forEach(mb -> innerMapper.addMapping(mb.get()));
}
}

Spring & Java Generics - Getting instance of one service in abstract controller

I have a typed service interface:
public interface BaseArticleService<T extends BaseArticle> {
T getById(Long id);
}
And have two interfaces which extends it:
public interface AccArticleService extends BaseArticleService<AccArticle> {
}
public interface ExpArticleService extends BaseArticleService<ExpArticle> {
Long getCount();
}
Then I have a similar architecture for controllers:
public abstract class BaseArticleController<T extends BaseArticle> {
#Autowired
BaseArticleService<T> baseArticleService;
}
And:
#Controller
#RequestMapping(value = "/exp/articles")
public class ExpArticleController extends BaseArticleController<ExpArticle> {
}
#Controller
#RequestMapping(value = "/acc/articles")
public class AccArticleController extends BaseArticleController<AccArticle> {
}
Now if I want to get my ExpArticleService instance of the BaseArticleService that is injected in my BaseController, how can I achieve this?
If I do this:
public BaseArticleService<ExpArticle> getExpArticleService() {
return super.baseArticleService;
}
then I cannot call my getCount() method like getExpArticleService().getCount()
And cannot do this neither:
public ExpArticleService getExpArticleService() {
return super.baseArticuloService;
}
So what's the solution? Maybe inject another ExpArticleService in my ExpArticleController?
When using DI you are by definition relying on the interface. If you inject BaseArticleService then the only method available to you are the methods defined in this interface. In your case T getById(Long id);
Your way is not a bad way, you have a generic super class which allow you to initialise the interface with different parameters very easily, but you shouldn't expect to explicitely get any of the specific implementation. (maybe you could check and cast but it is not clean there).
As already stated you should extract the specific implementation in another class and directly inject this one in the controller requiring it. Keep your generic though, it is a nice way to to handle all the parametrized methods that will be shared between your controllers

Spring switch implementations based on a runtime condition

This is a simplified version of what I am trying to achieve.
I have multiple implementations of the same interface. Based on the user input at runtime I want to pick the correct implementation.
For example suppose I an interface called Color. There are many classes that implement this interface, the Red class, the Blue class, the Green class and so on.
At run time I need to pick implementations based on the user input. One way to achieve this would be something like this
#Autowired
#Qualifier("Red")
private Color redColor;
#Autowired
#Qualifier("Green")
private Color greenColor;
private Color getColorImplementation()
{
if(userInput=="red")
{
return redColor;
}
else if(userInput=="green")
{
return greenColor;
}
else
{
return null;
}
}
But the problem with this is that everytime a new implementation is added, I would have to update the code that picks the implementation, which beats the whole purpose of inversion of control part of spring. What is the right way to do this using spring?
You could autowire all implementations of the interface in question and then decide based on properties provided by interface which to use.
#Autowired
private List<Color> colors;
public void doSomething(String input) {
colors.stream().filter(c -> c.getName().contains(input)).findFirst().ifPresent(c -> {
// something
}
}
This is also less magical and more in line with OO principles. Dependency injection is to wire up things initially, not for dynamic switching at runtime.
You want to Autowire the ApplicationContext, then you can get all the Color beans with Map<String, Color> colors = appContext.getBeansOfType(Color.class);. This presumes that the userInput and the bean name are identical.
If that isn't the case, a solution would be to add a getName() to the Color interface; then you can autowire a List<Color> and construct the Map yourself.
Can't you make the Color an Enum?
The Spring ServiceLocatorFactoryBean (scroll down to the middle) API was built just for this purpose:
Create a dummy interface (ColorFactory) that provides a single method such as Color getColor(String color)
Create the proxy bean instance for org.springframework.beans.factory.config.ServiceLocatorFactoryBean passing ColorFactory as the serviceLocatorInterface parameter
Define beans for all of your color implementations with names matching the parameter you'd like to pass to getColor
Inject the factory into the collaborators and invoke getColor as needed
You could contrive this with similar APIs on the ApplicationContext, but the advantage of this approach is that it abstracts Spring from your Java implementation (for XML configured projects).
Same issue happen in my implementation where in, the scenario was based on user input, where the respective interface implementation needs to be invoked.
This solve my problem:
**Base Interface**
#Service
public interface ParentInterface {
public String doThis(ClassA param);
}
**First Implementation**
#Component("FirstImp")
public class FirstServiceImp implements ParentInterface {
public String doThis(ClassA param){
}
**Second Implementation**
#Component("SecondImp")
public class SecondServiceImp implements ParentInterface {
public String doThis(ClassA param){
}
**Factory**
#Service
public class ServiceResolver {
#Autowired
#Qualifier("FirstImp")
private ParentInterface firstImpl;
#Autowired
#Qualifier("SecondImp")
private ParentInterface secondImpl;
public ParentInterface getInstance(String condition){
switch(condition) {
case "X": return firstImpl;
case "Y": return secondImpl;
default:
throw new IllegalArgumentException(condition);
}
}
}
**Controller**
#RestController
public class UserController {
#Resource
private ServiceResolver serviceresolver;
#PostMapping("/userbase/{inp1}/messages/{inptype}")
public ResponseEntity<String> sendData(#PathVariable String
inp1,#PathVariable String inptype, #RequestBody XYZBean msg)
{
for(ABC data : msg.getSubData())
serviceresolver.getInstance(data.getType()).doThis(msg);
return new ResponseEntity<String>("created",HttpStatus.OK);
}
}

Inheritance (Late Binding) via Dependency Injection in Java

I am using Spring DI to wire my components and I came across this issue.
I have a BaseService class which has multiple implementations. And the layer above it, has a builder which calls the service to get data to populate POJOs. Service implementation I need to call (ServiceA,ServiceB) changes according to the type of POJO I need to build.
In such case, how can I autowire the service, as it requires late binding the service. How can I tackle this kind of scenario? (Example in Spring DI would really help)
I read similar questions but could not find the answer. And I read that SOA patterns such as Service Host provide different solutions to exact use case.
Please help.
Thanks
How about using a FactoryBean:
public class BuilderFactory implements FactoryBean<Builder> {
#Autowired
private ApplicationContext appContext;
...
#Override
public Builder getObject() {
Builder builder = new Builder();
switch(something()) {
case "foo":
builder.service = new ServiceA();
break;
case "bar":
builder.service= new ServiceB();
break;
...
default:
//handle cases where it's unclear which type to create
}
return builder;
}
}
where Builder instances have a public/package-private field BaseService service that gets called in their getData(), buildPojos() and wherever other methods.
(you could also use static factory methods to instantiate Builder if you want this field to be private)
You can use ServiceLocatorFactoryBean. In your case you would do something like this:
public interface BaseServiceLocator {
BaseService lookup(String qualifier); //use whatever qualifier type makes sense here
}
<bean id="serviceLocatorFactoryBean"
class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface"
value="your.package.BaseServiceLocator" />
</bean>
Then your builder would look something like this:
public class Builder {
#Autowired
private BaseServiceLocator baseServiceLocator;
#Override
public YourReturnType businessMethod() {
SomeData data = getData();
BaseService baseService = baseServiceLocator(data.getType()); //here I am assuming that getType() is a String
//whatever
}
I had the same requirement in one of my projects. I used reflection to get the services according to the pojo requirement. This way there will be no static values even if you define new pojo and service in future you wont have to change any implementation.
I had named my pojos and Services similarly. ie
POJO Name:Pond5DownloadStrategy and ServiceName: Pond5DownloadStrategyService.
I defined all the services in spring. I had a DownloadStrategyFactory which had a single method
getService(Object obj). which is also instantiated as spring bean.
what getService method did is.
I get the POJO name as string using obj.getClass().getSimpleName() and then I append Service at the end. ex.
If I pass Pond5DownloadStrategy then I do AppContext.getBean("Pond5DownloadStrategyService");
Please look at my answer here.
Although is under spring batch topic it’s actually related to your question and the Strategy Design pattern.
StrategyA StrategyB are your ServiceA,ServiceB etc.
You need to use the StrategyLocator in your Builder class (in the original answer it’s equivalent is MyTaskelt). The look-up will be based on your pojo type.
strategy = strategyLocator.lookup(POJOs.class);
In the answer I suggested a PlugableStrategyMapper, but if you predefine all Servcies you can place them in a Map in the application-context.xml
For example, for manual binding:
public class Builder {
#Autowired
private Map<String, Service> services;
// Bind pojo classes to bean names.
private Map<Class<?>, String> binding;
public Service getService(Object object) {
return services.get(binding.get(object.getClass()));
}
public Map<Class<?>, String> getBinding() {
return binding;
}
public void setBinding(Map<Class<?>, String> binding) {
this.binding = binding;
}
}
However, manual binding could be repetitive so if you don't really need his flexibility, you could use a naming convention (#AmitChotaliya answer) or enforce the binding via Service method.
public interface Service {
Class<?> getTargetType();
}
public class Builder {
#Autowired
private Set<Service> services;
// Bind pojo classes to Services.
private Map<Class<?>, Service> binding = new ConcurrentHashMap<Class<?>, Service>();
#PostConstruct
public void init() {
for (Service service : services) {
binding.put(service.getTargetType(), service);
}
}
public Service getService(Object object) {
return binding.get(object.getClass());
}
}

Changing Guice bindings at runtime

I would like to be able to change the Guice injections at runtime to support multiple injections based on user input. This is what I would like to achieve:
public interface IDao {
public int someMethod();
}
public class DaoEarth implements IDao {
#Override
public int someMethod(){ ... }
}
public class DaoMars implements IDao {
#Override
public int someMethod(){ ... }
}
public class MyClass {
#Inject
private IDao myDao;
public int myMethod(String domain) {
//If Domain == Earth, myDao should be of the type DaoEarth
//If Domain == DaoMars, myDao should be of the type DaoMars
}
}
I was thinking of writing my own Provider, but I don't know how to use that provider to change my bindings at runtime. Any input is welcome and appreciated :)!
Update
Here's what I currently came up with, it's not as pretty as I'd like, so I'm still looking for feedback
public class DomainProvider {
#Inject #Earth
private IDaoProvider earthDaoProvider;
#Inject #Mars
private IDaoProvider marsDaoProvider;
public IDaoProvider get(Domain domain){
switch (domain){
case EARTH:
return earthDaoProvider;
case MARS:
return marsDaoProvider;
}
}
public IDaoProvider get(String domain){
Domain parsedDomain = Domain.valueOf(domain.toUpperCase());
return get(parsedDomain);
}
}
//MarsDaoProvider would be equivalent
public class EarthDaoProvider implements IDaoProvider {
#Inject #Earth
private IDao earthDao;
public IDao getDao() {
return earthDao;
}
}
// This means that in "MyClass", I can do:
public class MyClass {
#Inject
private DomainProvider domainProvider;
public int myMethod(String domain) {
IDaoProvider daoProvider = domainProvider.get(domain);
IDao dao = daoProvider.getDao();
//Now "dao" will be of the correct type based on the domain
}
}
//Of course elsewhere I have the bindings set like
bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class);
Your version is almost perfect as it is: You're going to need to inject some kind of object that returns one or the other based on code you write, and don't need assisted injection or anything like that. That said, you can skip some of the boilerplate:
public class DomainProvider {
// Just inject Providers directly without binding them explicitly.
#Inject #Earth Provider<IDao> earthDaoProvider;
#Inject #Mars Provider<IDao> marsDaoProvider;
public Provider<IDao> get(Domain domain){
switch (domain){
case EARTH:
return earthDaoProvider;
case MARS:
return marsDaoProvider;
}
}
public Provider<IDao> get(String domain){
Domain parsedDomain = Domain.valueOf(domain.toUpperCase());
return get(parsedDomain);
}
}
Your MyClass in that case would be exactly identical. Here, Provider is either the one-method generic interface com.google.inject.Provider, or the equivalent builtin javax.inject.Provider that it extends. Read more about Guice Providers on the relevant Guice wiki topic.
bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class);
// You can now inject "#Earth IDao" and also "#Earth Provider<IDao>".
Basically, if you bind a key Foo (to a class, provider, #Provides method, or instance), you automatically get to inject either a Foo or Provider<Foo> with no additional work. Providers are also a great way to ensure that you get a new instance with every call to get, if that's what you want; with your original, you'll always get the same instance of EarthDao or MarsDao for any given DomainProvider you inject. (If you have a scoped binding like #Singleton, Guice will respect that too; Provider just lets Guice get involved, rather than reusing a plain old Java reference.)
This means you can skip your custom EarthDaoProvider and MarsDaoProvider, unless you really need to perform any external initialization on them—at which point you'd probably be better off calling bind(EarthDao.class).toProvider(EarthDaoProvider.class) so the preparation also happens when injecting EarthDao directly. You could also just have DomainProvider return an IDao instance directly by calling get on the appropriate Provider, and be assured that it'll be a new instance every time.

Categories