Jackson ObjectMapper only interfaces known - java

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>);

Related

Kotlin Conflicting overloads: public open fun statements()

I have an interface Persistable which looks like this, the <T extends Statement<T>> List<Statement<T>> is to allow it to support both BoundedStatements and SimpleStatements in data stax 4.x driver.
public interface Persistable {
<T extends Statement<T>> List<Statement<T>> statements();
}
This java interface is inherited by Kotlin class A such that
data class UpdateRule(
private val something: S) : Persistable {
override fun statements(): List<Statement<BoundStatement> {
return PutKeyValue(Function(orgId, serviceId), JsonUtil.toJson(rule)).statements() //this returns BoundStatement
}
}
However, this gives the error Conflicting overloads.This code seems to work in Java(although with a warning), but in Kotlin it does not allow at all, how can I resolve this while also making sure parent interface remains generic to both Bound and Simple Statement?
You seem to misunderstand what the generics in Persistable mean. As it is written right now, you are supposed to implement the statements method so that it can handle any kind of T that extends Statement<T>. The generics there doesn't mean "implement this by choosing a kind of statement that you like".
It only produces a warning in Java because Java's generics is broken. Because of type erasure, List<Statement<BoundStatement> and List<Statement<T>> both erase to the same type - List, so the method in UpdateRule does implement the method in the interface if you consider the erasures. OTOH, type erasure isn't a thing in Kotlin (at least not in Kotlin/Core).
To fix this, you can move the generic type parameter to the interface:
public interface Persistable<T extends Statement<T>> {
List<Statement<T>> statements();
}
data class UpdateRule(private val something: S) :
Persistable<BoundStatement> {
override fun statements(): List<BoundStatement> =
PutKeyValue(Function(orgId, serviceId), JsonUtil.toJson(rule)).statements()
}
Notice how when we are implementing the interface, we can now specify the specific T that we are implementing for.
In Java just like in Kotin, the value of the type parameter of a generic method is determined by the caller of the method, and can be different at every call of the method, even on the same instance.
In your specific case, with the Java interface declared like this, statements() is supposed to be implemented in such a way that the caller can choose which type of statement will be returned by a given call to this method. This is not the case in your implementation, and that's why Kotlin doesn't allow it. As pointed out by #Sweeper, Java is broken in this respect and might let you get away with a warning.
This is different when using a generic class or interface. If you define the type parameter at the class/interface level, then the value of that type parameter is determined at construction time of the class, or can be fixed by subclasses. For a given instance, all calls to the method will return a well known type, which is (I believe) what you want here.
You can do this in Java:
public interface Persistable<T extends Statement<T>> {
List<Statement<T>> statements();
}
And then in Kotlin:
data class UpdateRule(
private val something: S
) : Persistable<BoundStatement> {
override fun statements(): List<BoundStatement> {
return PutKeyValue(Function(orgId, serviceId), JsonUtil.toJson(rule)).statements() //this returns BoundStatement
}
}

Name Clash, override fail, on a class implementing two interfaces with same erasure

I am creating a class that overrides a method signature whose erasure is identical between 2 implemented interfaces, but with a minor difference in regards of the generic type (one is a method-inferred type, the other an inferred-class type). I am looking for a neat solution. I CAN ONLY edit the inherited class, not the original legacy interfaces.
To show the case, I made up an abstract sample, to understand the problem:
I got a Developer legacy parent class:
public class Developer<C>{
Rate<C> getRate(Taxes<C> tax){ /*...*/ }
}
I also got a Rentable legacy interface, with an almost identical signature
public interface Rentable {
<C> Rate<C> getRate(Taxes<C> taxes);
}
As a developer is not rentable, in my model, I create an special
developer which is both a Developer, and Rentable material.
public class OutsourcableDeveloper<C>
extends Developer<C>
implements Rentable{
#Override
public Rate<C> getRate(Taxes<C> taxes){ /*...*/}
}
and then I got the infamous
Name clash: The method getRate(Developer.Taxes) of type
OutsourcableDeveloper has the same erasure as
getRate(Developer.Taxes) of type Rentable but does not override it
How can I get rid of it, so OutsourcableDeveloper.getRate() hides
both Developer and Rentable. getRate()?
It seems a bit illogical to fail a common override but then disallowing extending both signatures as the erasures are equal.
Does it really matters so much the fact that one of the supertypes infers type from de method and the other from the class specially when I'm not going to call any super in my implementation? Is there perhaps a trick to overcome the issue given this simplification?
EDIT: I opened a more abstract, less solution-oriented to my actual problem, question to discuss the inheritance design problem which I believe is the correlated essence of the actual issue I am having: Why can't I extend an interface "generic method" and narrow its type to my inherited interface "class generic"?
EDIT2: Previous question lead me to the answer posted here
Well they are actually not equal. Because any Rentable-Instance allows any typeparameter T to be given, while the OutsourcableDeveloper restricts it.
Of course you can assume that in your case it is easy to use the
<C> Rate<C> getRate(Taxes<C> taxes);
Version of the interface. But expect how confused a developer could be, if he wants to subclass OutsourceableDeveloper. From the definition of Developer he can assume that the Method getRate is fixed to C but actually it can suddenly take any value. -> allowing this would lead to confusion.
What i can offer you is the following code-example, which may be suitable for your case. Although it definitely will be inconvenient to use it. But as you forward all methods to the OursourcableDeveloperRentable it is possible. The comments should explain how it works.
//This class itself can be added to any Developer-lists
public class OutsourcableDeveloper<C> extends Developer<C> {
public final OutSourcableDeveloperRentable RENTABLE_INSTANCE = new OutSourcableDeveloperRentable();
#Override
public Rate<C> getRate(final Taxes<C> taxes) {
// Simply forward to the more general getRate instance.
return this.RENTABLE_INSTANCE.getRate(taxes);
}
public void exampleBehaviourA() {
//Example for how you can make both objects behave equally.
}
// This class can be added to the lists requiring a Rentable
// And the original value can be retrieved by both classes.
public class OutSourcableDeveloperRentable implements Rentable {
public final OutsourcableDeveloper<C> PARENT_INSTANCE = OutsourcableDeveloper.this;
//This method is the one to implement because it is more general than
//the version of OutsourcableDeveloper.
#Override
public <T> Rate<T> getRate(final Taxes<T> taxes) {
// Do your work.
return null;
}
public void exampleBehaviourA() {
//Just an example - Maybe for you it makes for sence to
//forward the method of Oursoursable-Developer to here.
//Then all Behaviour would be found in this class.
OutsourcableDeveloper.this.exampleBehaviourA();
}
}
}
Ok, I found a way to solve it. It's clumpsy, but it's the easier one if the architecture is not very complex, inspired by my Why can't I extend an interface "generic method" and narrow its type to my inherited interface "class generic"? own answer:
public class OutsourcableDeveloper<C>
extends Developer<C>
implements Rentable{
/* This might not be needed if we don't need to extract C from taxes parameter */
final Class<C> currencyClass;
public OutsourcableDeveloper(Class<C> currencyClass){ this.currencyClass = currencyClass;}
#Override
public Rate<C> getRate(#SuppressWarnings("rawtypes") Taxes taxes){
try{
C taxesCurrency = (C) currencyClass.cast(taxes.getCurrency()); //IF actually needed getting the typed instance
return new Rate<C>(taxesCurrency); //Or whatever processing
} catch (ClassCastException e){
throw new UnsupportedOperationException("OutsourcableDeveloper does not accept taxes in a currency that its not hims");
}
}
}
It is also possible to play with "extends Developer" without the generic type, so it is implictly raw. but we loose typing for the non-conflicting methods as well

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.

Guice generics - how can I make it less ugly?

I have an interface Producer<T> and a concrete FooProducer that implements Producer<Foo>. Binding this in guice looks ugly as sin:
bind(new TypeLiteral<Producer<Foo>>() {}).to(FooProducer.class);
I have lots of these such bindings. I have tried the following:
static <T> TypeLiteral<Producer<T>> producer() {
return new TypeLiteral<Producer<T>>(){};
}
With calls made in this way:
bind(ContainingClass.<Foo>producer()).to(FooProducer.class);
But it gives an error along the lines of Producer<T> is not specific enough....
Am I going about this in the wrong way?
Instead of
bind(new TypeLiteral<Producer<Foo>>() {}).to(FooProducer.class);
try a convenience method like
static <T> Key<Producer<T>> producerOf(Class<T> type) {
return (Key<Producer<T>>)Key.get(Types.newParameterizedType(Producer.class,type));
}
and then in your module
bind(producerOf(Foo.class)).to(FooProducer.class);
That unchecked cast should be safe. Key is com.google.inject.Key and Types is com.google.inject.util.Types.
good luck
You can save 8 characters by typing new Key<Producer<Foo>>(){} rather than new TypeLiteral<Producer<Foo>>(){}. Or by using the equivalent #Provides method:
#Provides
public Producer<Foo> provideFooProducer(FooProducer fooProducer) {
return fooProducer;
}
I believe that due to how TypeLiterals work, you have to actually write new TypeLiteral<Producer<Foo>>(){} or the necessary type information will not be available. They utilize the fact that a class that has fully specified its generic types can have information on those types retrieved. When you write new TypeLiteral<Producer<T>>(){}, you aren't specifying what T is, so that information isn't available.
It's subjective, but I don't think creating a type literal looks too ugly, considering what it does.
As an aside, I don't know what your Producer interface does, but if it is just used for producing instances of T (with a method that takes no arguments), you could use Guice's Provider interface instead. Then you just have to do:
bind(Foo.class).toProvider(FooProvider.class);
And you can inject a Foo or a Provider<Foo> anywhere.

Java generics question - Class<T> vs. T?

I'm using Hibernate validator and trying to create a little util class:
public class DataRecordValidator<T> {
public void validate(Class<T> clazz, T validateMe) {
ClassValidator<T> validator = new ClassValidator<T>(clazz);
InvalidValue[] errors = validator.getInvalidValues(validateMe);
[...]
}
}
Question is, why do I need to supply the Class<T> clazz parameter when executing new ClassValidator<T>(clazz)? Why can't you specify:
T as in ClassValidator<T>(T)?
validateMe.getClass() as in ClassValidator<T>(validateMe.getClass())
I get errors when I try to do both options.
Edit: I understand why #1 doesn't work. But I don't get why #2 doesn't work. I currently get this error with #2:
cannot find symbol
symbol : constructor ClassValidator(java.lang.Class<capture#279 of ? extends java.lang.Object>)
location: class org.hibernate.validator.ClassValidator<T>
Note: Hibernate API method is (here)
Because T is not a value - it's just a hint for the compiler. The JVM has no clue of the T. You can use generics only as a type for the purposes of type checking at compile time.
If the validate method is yours, then you can safely skip the Class atribute.
public void validate(T validateMe) {
ClassValidator<T> validator =
new ClassValidator<T>((Class<T>) validateMe.getClass());
...
}
But the ClassValidator constructor requires a Class argument.
Using an unsafe cast is not preferred, but in this case it is actually safe if you don't have something like this:
class A {..}
class B extends A {..}
new DataRecordValidator<A>.validate(new B());
If you think you will need to do something like that, include the Class argument in the method. Otherwise you may be getting ClassCastException at runtime, but this is easily debuggable, although it's not quite the idea behind generics.
Because ClassValidator is requiring a Class object as its parameter, NOT an instance of the class in question. Bear in mind you might be able to do what you're trying to do with this code:
ClassValidator<? extends T> validator = new ClassValidator<? extends T>(validateMe.getClass());

Categories

Resources