Inheritance and REST API Controllers - Dealing with Subclasses - java

I have the following class hierarchy for Coupon and Deals platform am developing::
Promotion - abstract
- Coupon
- Sale
- Deal
(Coupon, Sale and Deal inherit from Promotion. Promotion has a string attribute called type and an abstract method that initializes the the type attributes of the subclasses to a string value. For instance the type in coupon gets the value "Coupon" etc...)
For each subclass, I have a DAO and Service classes like CouponDAO, CouponService, etc.
In the front-end users can create Coupon or Sale or a Deal through Angular 2 interface so I decided to have the following controllers:
PromotionController - abstract
- CouponController
- SaleController
- DealController
(CouponController, SaleController, DealController inherit from PromotionController )
The PromotionController will contain all the common CRUD functions common to all subclasses and in the specific controllers I will handle specific operations meant for those classes.
A) The issue am facing now is how to instantiate the correct object coming from the client side. For instance when a user submit a Coupon or a Sale or a Deal how do I instantiate the right object. For instance in the PromotionController I have a function like this::
#RequestMapping(value=CREATE_PROMO, method=RequestMethod.POST)
public ResponseEntity<?> create(#RequestBody Promotion promotion){
promotionService.save(promotion);
return new ResponseEntity<>("", HttpStatus.OK);
}
Promotion which is abstract is the argument of the function. Should I use the factory pattern and the **type** attribute to create the right object?
For instance if the type="Coupon" then I create Coupon object, if it is "Sale" then I create the Sale object
B) Since the controller uses the Services objects it means that I have to declare all the three services objects in the PromotionController. Because after instantiating the right object, I need to call its corresponding service to do the job. In the method above I have promotionService which I think should be replaced with the right service of subclass
C) I am looking for how to handle REST APIs that deals with subclasses in the real world like the situation I have described above
D) I was thinking of making it easy for myself by copying all the CRUD operations to their specific controllers but it seems that will be repetitive code.
I think there is a better way that can be done.
I have also tried if I can find an open source project that deals with this situations but it seems all the projects I found use one class and not inheritance. Their REST/APIs don't handle inheritance situations

In my view, keep your endpoints simple. From a REST API standpoint, create individual or only one controller and use the following patterns after the controller layer. From what I have seen, it is always better to keep REST endpoints away from inheritance/reuse and apply it later after receiving and validating the requests.
To instantiate service/helper layer from controllers, use factory method pattern:
https://en.wikipedia.org/wiki/Factory_method_pattern
Create a PromotionServiceFactory which returns the PromotionService implementation depending upon the promotion type.
In controller, invoke corresponding method of promotion service using the factory. The factories still accept arguments of type Promotion.
#RequestMapping(value=CREATE_COUPON, method=RequestMethod.POST)
public ResponseEntity<?> create(#RequestBody Promotion promotion){
//helper if adding one more helper layer. The factory invocation is then //transferred to the helper layer
PromotionService couponService = promotionServiceFactory.get(PROMOTYPES.COUPON);
couponService.save(promotion);
return new ResponseEntity<>("", HttpStatus.OK);
}
From your questions, it seems like that there are common CRUD/other methods for different promotion types. This is a good candidate of the template pattern in the service layer if some of the steps/sub-tasks are same for every promotion and the others vary. Otherwise, you could just store the common CRUD methods by creating an abstract promotion service.
https://en.wikipedia.org/wiki/Template_method_pattern
Create an abstract promotion service with the primary method and implementations of common CRUD methods. Create individual implementations of other promotion service types with respective varying methods.

I think you can handle this in two ways depending upon the logic.
If you want to keep everything Separate then create a difference endpoints for coupon/deal/sale. That way every endpoint will call its controller and so on.
2) If you think code is same that you can use abstract factory pattern to instantiate the correct service and DAO object.
It all depends on your business requirement, I would prefer the second way if code logic is almost same. One controller per inheritance, so that in future if hierarchy increases you do not need to create multiple classes until required.

to answer you (A), I think you could use requestObject.instanceOf() method, to tell the correct subclass type, then handle with correct handler.

Related

Strategy Pattern using java 8 and service injection

I'm trying to implement the Strategy Pattern for some custom validation that doesn't involve only validation input with basic operations but I do need to call some other services to validate the data.
At the beginning I used the example mentioned here which uses enums to have different strategies but of course it was not possible to inject my services in the enum so now I'm looking at this that leverages to java 8 for more clarity.
My idea is to have an interface with has one method validate() and have generic input for different objects I could send it and then a class implementing that interface that would have different validations based on object type and dispatches requests to different services, but on the other hand I'm kinda loosing the enum advantage on having different strategies which I could select for instance based on specific user settings.
Any idea how to have both of these advantages?
I would say that enums and the strategy pattern don't really mix.
The ideal use case for an enum is something that represents an exhaustive set of choices. DayOfWeek representing Monday to Sunday, for example. The problem with using this, in addition to not being able to autowire any other beans, is that your enum will continue to grow as the number of validations increase.
The strategy pattern allows you to use a potentially infinite number of possible strategies, provided it obeys the contract. Take Collections.sort(List<T> list, Comparator<? super T> c), for example. There could be no exhaustive list of possible comparators, because it could never fulfill everyone's use-cases.
It makes more sense to define each of your possible strategies as a component
#Component
class NonNullValidationStrategy implements ValidationStrategy {
private final MyService service;
//constructor
#Override
public boolean isValid(MyClass foo) {
return foo != null;
}
}
How you would obtain an instance of the right strategy when you need it will depend on details you haven't provided. Maybe autowiring with a qualifier is a possibility.
Spring already has it's own way of defining validations, via interfaces and annotations. I suggest you pursue that before rolling your own solution.
It'd like to suggest using javax.validation groups, see more about it here especially #Validated(OnCreate.class)
If you want to apply strategy pattern at the controller level and deeper than see this article and especially my comment, because there is described not a pretty clean solution.

WS to Service concern

I have a Rest layer that call the Service layer.
My language is Java with Spring Framework
With some code would be:
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Entity get(#PathVariable("id") Long id) {
Entity entity = new Entity();
entity.setId(id);
return entityService.get(entity);
}
Well.... here are my questions:
Is it better to have a generic method in Service layer to hold the
parameters and filter to get and etc?
Is it better to have unit methods to filter the get like:
entityService.getByID(id);
entityService.getByValue1(value1);
entityService.getByIDAndValue1(id, value1);
Is it better to set the properties of Entity at Rest layer and call
service passing an object?
I think you may have some separate methods for more frequent use cases, like findByPrimaryKey(id) or findByName, and also a find by example method that will find entity by all not null fields in given entity.
You can also define a Business aware query interface (i mean no database layer query) to find objects, But this will complicate your rest service layer code so i prefer separated and simple methods that will make your service layer more readable.
There is also a Parameters Object design pattern, that mean grouping logically related parameters in object, eg. start date and and date as DateRange object.
But is useful when some logically related sequence of objects are passed as parameters to various methods. For example contact parameter may contain address, Zipcode and tel.

Chain of Responsibility design pattern confusion

I understand the concept of Chain of Responsibility Pattern but maybe I'm wrongly using it.
I have several types of product and I have a controller that controls the interface that is displayed for each of these types of product. The user selects the type of product and each controller is responsible for showing and interacting with the appropriate interface.
For this, I'm using the chain of responsibility pattern which doesn't sound okay I think. What I'm doing is creating a chain of controllers and, as soon as I get the product type request, I just pass it to the chain of controllers and let the appropriate controller implement the request.
But when thinking, the same could have been achieved using a simple factory but with many conditional statements.
What do you think about the use of chain of responsibility in this situation?
As for me this task is defenitely not for chain of responsibility.
Usually in chain of responsibility the order of chain elements matters and here it is not the case.
I would try to do the following.
Create some kind of registry, which contains a map with key for productType and value for controller.
Sample implementation:
class ControllerRegistry
{
//declaration for map and constructor
public void Register(string productType, IProductController controller)
{
_map.Add(productType, controller);
}
public IProductController Find(string productType)
{
return _map[productType];
}
}
And during application startup you should register all you controllers by calling ControllerRegistry.Register method.
You get appropriate controller by calling ControllerRegistry.Find method.
As compared with chain of responsibility you will avoid the performanse hit if number of product types is large.
EDIT
Same task topic Design pattern for handling multiple message types

Java - Designing a validator, class hierarchy

I'm working on designing a validator for certain objects (fields of those objects). These objects are enclosed in one, bigger object - container.
Example: Car as a container . Consists of Wheels, Engine, Body.
Lets say i need to validate if wheels have correct diameter, engine has correct capacity, body has certain length etc.
Theoretically I think I should validate everything before construction of a container (car).
What is the best way to achieve this? Do I make an abstract validator class with validate() method and implement it in every enclosed class? What about the container, do I just not include it at all in the validation process? Thanks for help.
I'd suggest you not to put the validation logic inside the classes you're going to validate.
I find it better to keep those classes as mere value objects, and create a parallel hierarchy of validators, roughly one for each entity to be validated. Alternatively, you could also create a single validator that can validate all the entities: however, this solution is less scalable and could bring you to violate the open-closed principle when you have to add a new entity (e.g. you want to deal also with the rear-view mirrors of the car).
Assuming you choose the one entity : one validator approach, the validator of the container will first validate the components inside the container and then validate if they fit together.
Please consider also the possibility of using validator frameworks such as Apache Commons Validator, that can save you from writing boilerplate code. However, since I don't know what kind of complex validation you have to perform, I don't know if it fits your needs.
Furthermore, I don't think you should be worried of validating everything before it is constructed. Just construct it and validate afterwards: then, if it violates the validation rules, you can discard it (i.e. don't persist it anywhere).
piggy backing off of gd1 answer, I agree. One such way would be to have a ValidatorAdapter for each of your value objects. So it would look like this:
public class GreenCarValidator {
public GreenCarValidator(Car car) {
// save reference
}
#Override
public boolean isValid() {
return car.getColor().equals("green");
}
}
public class RedCarValidator {
public RedCarValidator(Car car) {
// save reference
}
#Override
public boolean isValid() {
// you could compose more validators here for each property in the car object as needed
return car.getColor().equals("red");
}
}
Now you can have many types of validators for a single type of object, dynamic and configurable at runtime. Should you put the "valid()" method inside the classes the classes as gd1 suggest you not do, you would lose this flexibility.
You could create a ValidatablePart interface with a validate method, have all parts implement this interface, and then have the container validate all inclosed parts as they are being added to the container or perhaps when calling the the container's build or whatever method that is supposed to construct it.
Your Container class could follow the Template Method Design Pattern.

Interfaces and #RequestBody

I'm currently working on a project which allows users to book (via the web) the use of a chosen resource for a given period of time. In this program I am trying to keep with Spring's philosophy (and the general best practice) of programming to interfaces and as such I try to use interfaces anywhere where functionality is repeated among concrete classes.
One interface I have created is called a BookableResourceController which specifies the methods needed by a controller to handle the minimum required functionality for any type of resource to be booked. I also make use of a second interface, BookableResource, which identifies which objects model a resource that is allowed to be booked through the application.
The problem I am currently running into is that a few of the methods defined by BookableResourceController use the #RequestBody mapping to convert a JSON object into a method parameter, and since Jackson can only convert JSON into "SimpleType" objects, I receive an error if I specify the input parameter to be a BookableResource.
#RequestMapping(value="/delete.html", method = RequestMethod.POST)
public ModelAndView processDeleteResource(
#RequestBody BookableResource resource);
Can not construct instance of
org.codehaus.jackson.map.type.SimpleType,
problem: abstract types can only be
instantiated with additional type
information
From what I can tell this error means that I will need to define a specific implementation of BookableResource, meaning I will most likely need to exclude these methods from the interface even though any controller that is to be used for this purpose will require those methods.
What I am asking is if anyone knows a way to define an interface as the object that is expected from an #RequestBody mapping using JSON, or does anyone have any suggestions of how to structure my contoller interface in order to include these methods?
Cheers
I'm not sure it would work, but you can try to make it generic:
public interface BookableResourceController<R extends BookableResource> {
#RequestMapping(value="/delete.html", method = RequestMethod.POST)
public ModelAndView processDeleteResource(#RequestBody R resource);
}
Additional way to go that can be used is to annotate interface with Jackson annotation:
#JsonDeserialize(as=BookableResourceImp.class)
(possibly using mix-in annotations if one does not want to add it directly in interface class)
EDIT: Another possibility is to use SimpleModule method addAbstractTypeMapping() to specify implementation type. This avoids linkage from interface to implementation, and may (or may not) be more convenient way to register this aspect.

Categories

Resources