I'm working with JSON data and converting it into Java POJO class, then I built an interface like this:
public interface DataUtil<T extends DataUtil<T>> {
default T someDefaultFn() { ... };
}
And I used this interface for some POJO data class like:
public MyPoJo extends DataUtil<MyPojo> { ... }
And I get stuck when I to try check the type variable Class<FType> (a FieldType of any fields are declared inside T class) whether FType extends DataUtil<FType extends DataUtil<FType>> or not? I'm also trying to research the java.reflect package but did not find the expected answer. Can anyone help me to resolve this problem or find another design solution for this scenario?
Let's say I wanted to define an interface which represents a call to a remote service.
Both Services have different request and response
public interface ExecutesService<T,S> {
public T executeFirstService(S obj);
public T executeSecondService(S obj);
public T executeThirdService(S obj);
public T executeFourthService(S obj);
}
Now, let's see implementation
public class ServiceA implements ExecutesService<Response1,Request1>
{
public Response1 executeFirstService(Request1 obj)
{
//This service call should not be executed by this class
throw new UnsupportedOperationException("This method should not be called for this class");
}
public Response1 executeSecondService(Request1 obj)
{
//execute some service
}
public Response1 executeThirdService(Request1 obj)
{
//execute some service
}
public Response1 executeFourthService(Request1 obj)
{
//execute some service
}
}
public class ServiceB implements ExecutesService<Response2,Request2>
{
public Response1 executeFirstService(Request1 obj)
{
//execute some service
}
public Response1 executeSecondService(Request1 obj)
{
//This service call should not be executed by this class
throw new UnsupportedOperationException("This method should not be called for this class");
}
public Response1 executeThirdService(Request1 obj)
{
//This service call should not be executed by this class
throw new UnsupportedOperationException("This method should not be called for this class");
}
public Response1 executeFourthService(Request1 obj)
{
//execute some service
}
}
In a other class depending on some value in request I am creating instance of either ServiceA or ServiceB
I have questions regarding the above:
Is the use of a generic interface ExecutesService<T,S> good in the case where you want to provide subclasses which require different Request and Response.
How can I do the above better?
Basically, your current design violates open closed principle i.e., what if you wanted to add executeFifthService() method to ServiceA and ServiceB etc.. classes.
It is not a good idea to update all of your Service A, B, etc.. classes, in simple words, classes should be open for extension but closed for modification.
Rather, you can refer the below approach:
ExecutesService interface:
public interface ExecutesService<T,S> {
public T executeService(S obj);
}
ServiceA Class:
public class ServiceA implements ExecutesService<Response1,Request1> {
List<Class> supportedListOfServices = new ArrayList<>();
//load list of classnames supported by ServiceA during startup from properties
public Response1 executeService(Request1 request1, Service service) {
if(!list.contains(Service.class)) {
throw new UnsupportedOperationException("This method should
not be called for this class");
} else {
return service.execute(request1);
}
}
}
Similarly, you can implement ServiceB as well.
Service interface:
public interface Service<T,S> {
public T execute(S s);
}
FirstService class:
public class FirstService implements Service<Request1,Response1> {
public Response1 execute(Request1 req);
}
Similarly, you need to implement SecondService, ThirdService, etc.. as well.
So, in this approach, you are basically passing the Service (to be actually called, it could be FirstService or SecondService, etc..) at runtime and ServiceA validates whether it is in supportedListOfServices, if not throws an UnsupportedOperationException.
The important point here is that you don't need to update any of the existing services for adding new functionality (unlike your design where you need to add executeFifthService() in ServiceA, B, etc..), rather you need to add one more class called FifthService and pass it.
I would suggest you to create two different interfaces every of which is handling its own request and response types.
Of course you can develop an implementation with one generic interface handling all logic but it may make the code more complex and dirty from my point of view.
regards
It makes not really sense to have a interface if you know that for one case, most of methods of the interface are not supported and so should not be called by the client.
Why provide to the client an interface that could be error prone to use ?
I think that you should have two distinct API in your use case, that is, two classes (if interface is not required any longer) or two interfaces.
However, it doesn't mean that the two API cannot share a common interface ancestor if it makes sense for some processing where instances should be interchangeable as they rely on the same operation contract.
Is the use of a generic interace (ExecutesService) good in the case
where you want to provide subclasses which require different Request
and Response.
It is not classic class deriving but in some case it is desirable as
it allows to use a common interface for implementations that has some enough similar methods but don't use the same return type or parameter types in their signature :
public interface ExecutesService<T,S>
It allows to define a contract where the classic deriving cannot.
However, this way of implementing a class doesn't allow necessarily to program by interface as the declared type specifies a particular type :
ExecutesService<String, Integer> myVar = new ExecutesService<>();
cannot be interchanged with :
ExecutesService<Boolean, String> otherVar
like that myVar = otherVar.
I think that your question is a related problem to.
You manipulate implementations that have close enough methods but are not really the same behavior.
So, you finish to mix things from two concepts that have no relation between them.
By using classic inheriting (without generics), you would have probably introduced very fast distinct interfaces.
I guess it is not a good idea to implement interface and make possible to call unsupported methods. It is a sign, that you should split your interface into two or three, depending on concrete situation, in a such way, that each class implements all methods of the implemented interface.
In your case I would split the entire interface into three, using inheritance to avoid doubling. Please, see the example:
public interface ExecutesService<T, S> {
T executeFourthService(S obj);
}
public interface ExecutesServiceA<T, S> extends ExecutesService {
T executeSecondService(S obj);
T executeThirdService(S obj);
}
public interface ExecutesServiceB<T, S> extends ExecutesService {
T executeFirstService(S obj);
}
Please, also take into account that it is redundant to place public modifier in interface methods.
Hope this helps.
I've got around 5 objects that I want to do similar things with.
I figured out that not to polute the code I will put a logic for those objects in one place.
public class MetaObjectController<T extends MetaObject> {
#Autowired
private final MetaObjectRepository<T> repository;
// generic logic
Here's how repository looks:
public interface MetaObjectRepository<T extends MetaObject> extends GraphRepository<T> {
T findByName(String name);
}
Now, I create concrete class which uses delegation:
public class ExperimentalController {
#Autowired
private final MetaObjectController<MetaCategory> metaController;
#RequestMapping(method = RequestMethod.POST)
public void add(#RequestBody MetaCategory toAdd) {
metaController.add(toAdd);
}
Now, when I look at the generated queries I see, that although instantiated correctly, repository puts MetaObject as an entity name instead of runtime type.
Is there a way to force the repository to use runtime type?
Please don't advise to put a #Query annnotation. That's not what I am looking for.
This is most probably due to type erasure: at runtime there is only the type constraint available which is MetaObject. If you want to use (via spring-data) the actually relevant subclass you will have to create explicit interfaces of the MetaObjectRepository like this:
public class Transmogrifier extends MetaObject
public interface MetaTransmogrifierRepository
extends MetaObjectRepository<Transmogrifier> {}
I have a Spring bean defined like this:
package org.behrang.sample;
import foo.AbstractThirdPartyClass;
#Component
public class SampleBean extends AbstractThirdPartyClass<Input, Output> {
#Override
public Optional<Output> process(Input input) {
}
}
The AbstractThirdPartyClass class is defined in a third-party library named foo.
I want to implement an advice that applies to all methods in the
org.behrang.sample package, so I have implemented something like this:
#Aspect
#Component
public class SampleAspect {
#Before("execution(public * org.behrang.sample..*.*(..))")
public void sampleBefore(JoinPoint joinPoint) {
}
}
However this is not advising SampleBean::process(Input). If I remove the extends AbstractThirdPartyClass<Input, Output>
part, then the process method is advised.
Is there an elegant way to workaround this problem? For example, I can define an interface in org.behrang.sample with one method like this:
public interface Sampler<I, O> {
public Optional<O> process(I input);
}
And make the SampleBean implement it too. But this is way too ugly and anti-DRY.
Also I have enabled AOP using #EnableAspectJAutoProxy(proxyTargetClass = true) as manu beans defined in this project are not implementing any interfaces.
I want my class to implement an interface, but I want to provide the implementation of the methods using ITD in an aspect. Is this possible?
Interface:
public interface CloningService<T> {
public T clone(T object);
}
Default implementation:
public class DefaultCloningServiceImpl implements CloningService<T> {
public T clone(T object) {
// implementation of the clone method
}
}
Specific implementation:
public class PersonService implements CloningService<Person> {
// no code (!)
}
The class PersonService would declare that it implements the CloningService interface, but the actual implementation of the methods would be provided in DefaultCloningServiceImpl and an aspect would introduce them to PersonService.
I followed the example on Eclipse.com and I tried to use #DeclareParents to achieve the above functionality. However, I was getting a compiler error from AspectJ, which had to do with generics. It's as if the #DeclareParents annotation did not expect the generics to be used...
Thank you.
I'd recommend that you use code style aspectj to solve this rather than annotation style.
This could be done simply by having an aspect like this:
aspect CloningServiceAspect {
declare parents : PersonService extends DefaultCloningServiceImpl<Object>;
}
To make this more general and attached to an annotation, you can do something like this:
aspect CloningServiceAspect {
declare parents : (#CloningService *) extends DefaultCloningServiceImpl<Object>;
}
And if you wanted to package this up into a standalone jar, just make sure to add all code that you want to weave adds this jar to its aspect path (if using compile-time weaving).
I found the solution! It involves using the #DeclareMixin annotation from AspectJ to mix the default implementation of the clone() method:
#Aspect
public class CloningServiceAspect {
#DeclareMixin(value = "(#CloningService *)")
public static CloningService<?> createImplementation() {
return new DefaultCloningServiceImpl<Object>();
}
}
And then my service is annotated with #CloningService instead of implementing the interface:
#CloningService
public class PersonService {
// no code
}