spring too many constructors argument using the same interface with qualifiers - java

This is more like a "good practice" question.
let's say i have an interface "MyInterface" and about 15 implementations of it.
I have an Object called "MyProcess" and the code looks like
private final List<MyInterface> myInterfaces;
public MyProcess(#Qualifier("impl1") MyInterface impl1,
#Qualifier("impl2") MyInterface impl2,
#Qualifier("impl3") MyInterface impl3,
#Qualifier("impl4") MyInterface impl4,
#Qualifier("impl5") MyInterface impl5,
#Qualifier("impl6") MyInterface impl6,
#Qualifier("impl7") MyInterface impl7,
#Qualifier("impl8") MyInterface impl8) {
this.myInterfaces = Stream
.of(impl1,
impl2,
impl3,
impl4,
impl5,
impl6,
impl7,
impl8)
.collect(toList());
}
The goal is to define different processes using some of the implementations of MyInterface in a specific order. The issue is that sonar rule S107 (constructor has 8 parameters which is greater than 7 authorized) is showing. I was wondering if this was a code structure issue or if i just had to ignore sonar on this. I dont feel like breaking SRP since the only goal of MyProcess is to define the list of MyInterface it needs.
Does anyone have a clue on how i could improve this code ? Maybe an other pattern to use ?
Thank you in advance for your time

One alternative is to add a method name() to MyInterface, which is implemented in each subclass as returning a constant String.
public MyProcess(List<MyInterface> impls) {
this.myInterfaces = new ArrayList<MyInterface>();
for(String name: Arrays.asList("impl1", "impl2"...) {
for(MyInterface impl: impls) {
if(name.equals(impl.name())) {
myInterfaces.add(impl);
}
}
}
}
I feel that hard-coding the names of the implementation in the process might not be ideal. If you already have 15 implementations, the odds are that you might in the future have to add one. And then you would need to update the Process as well.
You let the MyInterface return something else than a name, e.g. a 'purpose' and a 'priority', so the process could wire new implementations automatically in the correct place, but that depends on your usecase.

Related

Jackson ObjectMapper only interfaces known

If I want to read some JSON into an object, and I have the interface but must use the Spring context to get the implementation class, I need to use a SimpleAbstractTypeResolver to map the interface to the implementation. So far, so good, if I know in advance what interfaces go to what implementation. But if the interface has methods that return other interfaces--and possibly down the line recursively--and I don't necessarily know in advance, I thought I could use reflection to figure it out. So this is what I came up with, but the compiler does NOT like the line resolver.addMapping(method.getReturnType(), method.getReturnType());, says it's not applicable for these arguments. I'm pretty sure the types are okay for that method--any thoughts on how to make this happen?
for (Method method : clazz.getMethods()) {
if (method.getReturnType().isInterface() && method.getName().startsWith("get")) {
// getter method returns an interface so find its implementation class
Class beanClass = context.getBean(method.getReturnType()).getClass();
if (clazz.isAssignableFrom(beanClass)) {
resolver.addMapping(method.getReturnType(), method.getReturnType());
mapInterfaces(objectMapper, clazz, resolver);
}
}
}
Probably you need to review your types.
My guess is following:
resolver.addMapping(method.getReturnType(), beanClass);
(replace second parameter method.getReturnType() with beanClass)
or as an alternative (the code is not completely clear for me, sorry)
resolver.addMapping(clazz, beanClass);
You should put an Interface and Implementation into addMapping().
Example:
interface ITest{};
class TestImpl implements ITest {}
usage:
resolver.addMapping(ITest.class, TestImpl.class);
Probably you need to review your types.
My guess is following:
new ObjectMapper().writerFor(<Interface>.class).writeValuesAsArray(<Class>);

How to deal with abstract classes as entry api contracts for microservices and tackle polymorphism same time?

I am going through dozen tutorials which prove to me of very little help because production code is not an animal, bird or human. Not a weapon of type cutting or shooting it is much more complex to reason about.
So returning to reality, scenario:
service 1 is exchanging messages with service 2 through Kafka, messages are serialized/deserialized with Jackson, the model class is shared between services as jar.
Now the plague part, the culmination of evil :
#JsonTypeInfo(
use = Id.NAME,
property = "type",
visible = true
)
#JsonSubTypes({#Type(
value = InternalTextContent.class,
name = "text"
), #Type(
value = InternalImageContent.class,
name = "image"
), #Type(
value = InternalAudioContent.class,
name = "audio"
), #Type(
value = InternalCustomContent.class,
name = "custom"
)})
public abstract class InternalContent {
#JsonIgnore
private ContentType type;
public InternalContent() {
}
Obviously when the time will come to work with this content we will have something like:
message.getInternalContent
which results to a sea of switch statements, if conditions, instanceof and wait for it ... downcasting everywhere
And this is just one property example the wrapping object contains. Clearly I cannot add polymorphic behaviour to InternalContent , because hellooo it is within a jar.
What went wrong here? Is it even wrong?
How do I add polymorphic behaviour ? To add a new mitigating layer, I still need instanceof in some factory to create a new type of polymorphic objects family which are editable to add the desired behavior? Not even sure it is going to be better, it just smells and make me want to shoot the advocates which throw blind statement like instanceof with downcasting is a code smell" torturing people like me who genuinely care, which makes me wonder if they ever worked on a real project. I deliberately added system environment details to understand how to model not just the code but interaction between systems. What are possible redesign options to achieve the "by book" solution?
So far I can think of that sharing domain model is a sin. But then if I use different self-service-contained classes to represent same things for serialization/deserialization I gather flexibility but lose contract and increase unpredictability. Which is what technically happens with HTTP contracts.
Should I send different types of messages with different structures along the wire instead of trying to fit common parts and subtypes for uncommon in a single message type?
To throw more sand at OO , I consider Pivotal the best among the best yet:
https://github.com/spring-projects/spring-security/blob/master/core/src/main/java/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java
public boolean supports(Class<?> authentication) {
return (UsernamePasswordAuthenticationToken.class
.isAssignableFrom(authentication));
}
AuhenticationManager has a list of AuthenticationProviders like this and selects correct one based on the method above. Does this violate polymorphism ? Sometimes it all just feels as a hype...
Use the visitor pattern.
Example (I'll limit to two subclasses, but you should get the idea):
interface InternalContentVisitor<T> {
T visitText(InternalTextContent c);
T visitImage(InternalImageContent c);
}
public abstract class InternalContent {
public abstract <T> T accept(InternalContentVisitor<T> visitor);
// ...
}
public class InternalTextContent {
#Override
public <T> T accept(InternalContentVisitor<T> visitor) {
return visitor.visitText(this);
}
}
public class InternalImageContent {
#Override
public <T> T accept(InternalContentVisitor<T> visitor) {
return visitor.visitImage(this);
}
}
This code is completely generic, and can be shared by any application using the classes.
So now, if you want to polymorphically do something in project1 with an InternalContent, all you need to do is to create a visitor. This visitor is out of the InternalContent classes, and can thus contain code that is specific to project1. Suppose for example that project1 has a class Copier that can be used to create a Copy of a text or of an image, you can use
InternalContent content = ...; // you don't know the actual type
Copier copier = new Copier();
Copy copy = content.accept(new InternalContentVisitor<Copy>() {
#Override
public Copy visitText(InternalTextContent c) {
return copier.copyText(c.getText());
}
#Override
public Copy visitImage(InternalImageContent c) {
return copier.copyImage(c.getImage());
}
});
So, as you can see, there is no need for a switch case. Everything is still done in a polymorphic way, even though the InternalContent class and its subclasses have no dependency at all on the Copier class that only exists in project1.
And if a new InternalSoundContent class appears, all you have to do is to add a visitSound() method in the visitor interface, and implement it in all the implementations of this interface.

Spring:DI with interface with implementation class less restrictive exceptions

I have an implementation class which catches all the declared exceptions of a method of an Interface. As I inject and use the Interface instance variable inside a class and hope to call the implementation method - I am naturally getting a compiler error pointing that I either need to throw/catch the exceptions declared in parent.
Few options that come to my mind are these, but I don't like them. Just want to know the best way to go about this.
Cast the interface instance to impl
Create child interface with a method with no exceptions
May be just not declare exceptions in Interface. Just catch all of the possible exceptions in impl.
EDIT 1: Attached some example code
public interface ServiceUtilInterface {
public abstract String getMessage(String ID) throws CustomException;
}
#Component(value="MyServiceUtil")
public class MyServiceUtil implements ServiceUtilInterface {
#Override
public String getMessage(String ID) {
try{
//do something
}catch(CustomException e){
}
return "";
}
#Component
public class Usage {
#Autowired
ServiceUtilInterface serviceUtil;
public void someMethod(){
serviceUtil.getMessage("123");
//This where compiler expects me to throw /catch the exception defined in interface
}
}
UPDATE
Cast the interface instance to impl - never ever do that. If you use Spring then you never know what the implementation of an interface could be. This should be configuration dependent.
If you start do write jUnits you will probably need to use mock (fake) components for testing. Then if you try to cast your mock to a concrete implementation your code will fail. In other words you will never be able to write proper unit tests. The other thing is that if you add some Aspects or make a service #Transactional or #Validated then you wont be able to cast because instead of your implementation you may receive a proxy object.
and 3 that strongly depends on your code design. Try to find some materials about good practices for throwing and handling exceptions. There are some general rules about that. Probably no one can help you with this because this is service specific.

Determine if a Class implements a interface in Java

I have a Class object. I want to determine if the type that the Class object represents implements a specific interface. I was wondering how this could be achieved?
I have the following code. Basically what it does is gets an array of all the classes in a specified package. I then want to go through the array and add the Class objects that implement an interface to my map. Problem is the isInstance() takes an object as a parameter. I can't instantiate an interface. So I am kind of at a loss with this. Any ideas?
Class[] classes = ClassUtils.getClasses(handlersPackage);
for(Class clazz : classes)
{
if(clazz.isInstance(/*Some object*/)) //Need something in this if statement
{
retVal.put(clazz.getSimpleName(), clazz);
}
}
You should use isAssignableFrom:
if (YourInterface.class.isAssignableFrom(clazz)) {
...
}
you can use the below function to get all the implemented interfaces
Class[] intfs = clazz.getInterfaces();
You can use class.getInterfaces() and then check to see if the interface class is in there.
Class someInterface; // the interface you want to check for
Class x; //
Class[] interfaces = x.getInterfaces();
for (Class i : interfaces) {
if (i.toString().equals(someInterface.toString()) {
// if this is true, the class implements the interface you're looking for
}
}
You can also set the instance adding ".class"
Class[] classes = ClassUtils.getClasses(handlersPackage);
for(Class clazz : classes)
{
if(Interface.class.isAssignableFrom(clazz))
{
retVal.put(clazz.getSimpleName(), clazz);
}
}
A contribution for all the other answers, when possible do not use the most updated answer of method isAssignableFrom, even the "not great" answer of using clazz.getInterfaces() has better performance than isAssignableFrom.
A common mistake for developers when looking for an answer to the OP question, is to prefer isAssignableFrom when an instance is available, wrongly doing this:
if (IMyInterface.isAssignableFrom(myObject.getClass())) {
...
When possible, use IMyInterface.class.isInstance or instanceof as both of those have way better performance. Of course, as the OP stated; they have the drawback that you must have an instance and not just the class.
if (IMyInterface.class.isInstance(myObject)) {
...
if (myObject instanceof IMyInterface) { // +0.2% slower than `isInstance` (*see benchmark)
...
An even faster, but ugly solution would be to store an static Set with all the "valid" classes instead of checking them, this ugly solution is only preferred when you need to test classes a lot, as its performance outperforms all the other approaches for direct class check.
public static final Set<Class<?>> UGLY_SET = Stream.of(MyClass1.class, MyClass2.class, MyClass3.class).collect(Collectors.toCollection(HashSet::new));
if (UGLY_SET.contains(MyClass)) {
...
(*) JMH Benchmark for +0.2%
Please visit this answer from users #JBE, #Yura and #aleksandr-dubinsky, credits for them. Also, there's plenty of detail in that answer for the benchmark results to not be valid, so please take a look into it.

How can I replace reflection with guice?

I have long used reflection to decouple modules from "handlers".
I have a code base which is architected like this :
static enum AnimalHandlers {
Dog(Dog.class),
Cat(Cat.class);
private final Class c;
AnimalHandlers(Class class)
{
this.c=class;
}
public Class getAnimalHandler()
{
return c;
}
}
Then later in my code, I have a method which takes an "Animal" enum as input and uses reflection (that is, it gets the class from the enum and invokes "newInstance") to invoke the necessary handler.
I think the solution would be cleaner with Guice. How can I get rid of the enum/reflection and simply use guice to "hydrate" my control module with domain specific logic handlers?
You could well use a MapBinder<AnimalEnum, AnimalHandler>, and define a binding for each possible AnimalEnum value.
I think that there must be a better pattern here. I'm a little confused as to just how the Animal enum interfaces with the handler but I'll make some general suggestions and maybe one will stick.
I assume that there is no way to define the handlers in the Animal enum and you want to decouple the classes. Fine.
Could the the handlers register themselves with Animal.setHandler(...)? Then you could just call Animal.Dog.getHandler() to get Dog's handler.
I agree with #jfpoilpret that some sort of AnimalHandlerMapper would also be better. I assume there a common interface is possible, even if it just a marker interface.
Code:
private static Map<Animal, AnimalHandler> handlerMap
= new HashMap<Animal, AnimalHandler>();
static {
Dog dog = new Dog();
handlerMap.put(Animal.Dog, dog);
// we use the same handler twice here
handlerMap.put(Animal.Wolf, dog);
handlerMap.put(Animal.Cat, new Cat());
// do a Animal.values loop at the end to verify that everyone has a handler
}
public static AnimalHandler getHandler(Animal animal) {
return handlerMap.get(animal);
}
If for some reason you can't use the handler instances then I would do the same thing but with handler factories. So you've call handlerMap.get(animal).create(animal) or some such. This would be much cleaner than using reflection.
I'm not sure how Guice compares to Spring but if this was spring I would instantiate the handler beans and they would register with the AnimalHandlerMapper to completely decouple it.
Hope this helps.

Categories

Resources