Jackson constructParametricType is deprecated, but constructParameterizedType doesn't work the same - jackson

Here is my code snippet, and the newer "constructParameterizedType" doesn't match my needs (unless I am missing something, which I assume I am). I have a genericized class called Result where T is any basic class that extends my "Inflatable" base class. represents the data records coming back from Salesforce REST API... so here is example of code that is working:
Class c = Class.forName("sfshare.UserRecord" );
JavaType type = mapper.getTypeFactory().constructParametricType(Result.class, c);
Result<T> res = mapper.readValue(rspData, type);
But if I use the newer (non-deprecated) "constructParameterizedType()" method, this same code will not compile because it isn't matching the parameters of constructParameterizedType. But constructParameterizedType isn't in use much yet and there are no examples to use... only the Javadoc - which doesn't make sense for my use-case.

If you look at arguments and specifically Javadocs, you will note that there is a new type: 2nd argument is the intended 'target' for parameters.
To give an example of meaning is that if you want to construct equivalent of:
ArrayList<String>
what you want to pass as arguments are:
constructParameterizedType(ArrayList.class, List.class, String.class)
or, possibly, Collection.class for second argument.
Think of it as the underlying relevant type you are trying to provide parameters for.
The underlying reason for this change is somewhat complicated and has to do with handling of "add-on" interfaces like Iterable<T>: for those cases it is necessary to provide different classes.
But in most end-user use cases you will just need to pass the same class as first and second argument.

Try this:
Class c = Class.forName("sfshare.UserRecord");
TypeFactory typeFactory = mapper.getTypeFactory();
JavaType type = typeFactory.constructParametrizedType(Result.class, Result.class, c);
Result<T> res = mapper.readValue(rspData, type);
or if your Result<T> class implements an interface:
JavaType type = typeFactory.constructParametrizedType(Result.class, ResultInterface.class, c);

Related

Kotlin. How to get specific subclass of sealed class?

I'm using kotlin sealed class. And I need to retrieve specific subclass. My sealed class:
sealed class Course(
val type: Type
) {
data class ProgrammingCourse(val name: String, val detail: String) : Course(Type.PROGRAMMING)
object LanguageCourse: Course(Type.LANGUAGE)
.....
}
For example I have function which can return Course:
fun getCourse(): Course {
if(...)
return Course.ProgrammingCourse("test", "test")
else
return Course.LanguageCourse
}
In addition, I have a method that can only work with a specific subclass of the Course class. Fox example:
fun workWithCourse(course: Course.ProgrammingCourse) {
// here some logic
}
And now I'm trying to get the course using the method getCourse(), and then pass it to the method workWithCourse()
fun main() {
val course = getCourse()
workWithCourse(course)
}
Error:
Type mismatch.
Required:
Course.ProgrammingCourse
Found:
Course
But I know the course type - Type, parameter that each course has. Can I, knowing this Type, cast the course (which I retrieve from getCourse() method) to a specific subclass ? Is there such a way ?
Please help me
P.S.
I don't need type checks like:
if(course is Course.ProgrammingCourse) {
workWithCourse(course)
}
I need the subclass to be automatically inferred by the Type parameter, if possible.
P.S.2
The need for such a solution is that I have a class that takes a Course, it doesn't know anything about a particular course, at the same time the class takes the Type that I want to use for identification. This class also receives an interface (by DI) for working with courses, a specific implementation of the interface is provided by the dagger(multibinding) by key, where I have the Type as the key. In the same way I want to pass by the same parameter Type specific subclass of my Course to my interface which working with specific courses.
No, there is no way for automatic inference to the best of my knowledge.
You returned a Course, and that's what you have. Being sealed here does not matter at all. Generally what you do here is use the when expression if you want to statically do different things depending on the type, but if it's just one type (ProgrammingCourse) that can be passed to workWithCourse, then an if is probably right, with dispatch using as.
That said, this looks like counter-productive design. If you can only work with one course, why do they even share a top level interface? The way the code is written implies working is a function that can take any course, or should be a method member. Anything else is very confusing. Perhaps workWithCourse should take a Course and use the when expression to dispatch it appropriately?
In kotlin you can specify the class explicitly with as.
val course = getCourse()
if (type == Type.PROGRAMMING) {
workWithCourse(course as Course.ProgrammingCourse)
}
*thanks Joffrey for his comment
What you seem to be asking for is a compile-time guarantee for something that will only be known at runtime. You didn't share the condition used in getCourse(), but in general it could return both types.
Therefore, you need to decide what will happen in both cases - that's not something the compiler can decide for you via any "inference".
If you want the program to throw an exception when getCourse() returns something else than a Course.ProgrammingCourse, you can cast the returned value using as:
val course = getCourse() as Course.ProgrammingCourse
workWithCourse(course)
If you don't want to crash, but you only want to call workWithCourse in some cases, then you need an if or when statement to express that choice. For instance, to call it only when the value is of type Course.ProgrammingCourse, then you would write the code you already know:
if (course is Course.ProgrammingCourse) {
workWithCourse(course)
}
Or with a when statement:
val course = getCourse()
when (course) {
is Course.ProgrammingCourse -> workWithCourse(course)
is Course.LanguageCourse -> TODO("do something with the other value")
}
The when is better IMO because it forces you (or other devs in the team) to take a look at this when whenever you (or they) add a new subclass of the sealed class. It's easy to forget with an if.
You can also decide to not test the actual type, and focus on the type property like in #grigory-panov's answer, but that is brittle because it relies on an implicit relationship between the type property and the actual type of the value:
val course = getCourse()
if (type == Type.PROGRAMMING) {
workWithCourse(course as Course.ProgrammingCourse)
}
The main point of using sealed classes is so you can use their actual type instead of a manually managed type property + casts. So I'd say use only is X and don't set a type property at all. Using a sealed class allows Kotlin to type-check a bunch of things, it's more powerful than using such a property.

Map of generic interfaces in Kotlin

I stuck with some simple thing) Let's say I have following:
interface IMessagePayload // marker interface
data class IdPayload(
val id: Long
) : IMessagePayload
data class StringPayload(
val id: String,
) : IMessagePayload
Then I have a class:
data class Message<T : IMessagePayload>(
val id: String,
val payload: T,
)
Also I have some interface describing processor of this message:
interface IMessageProcessor<T : IMessagePayload> {
fun process(message: Message<T>)
}
And some implementation:
class ProcessorImpl : IMessageProcessor<IdPayload> {
override fun process(message: Message<IdPayload>) {
}
}
Now I wanna have a map of such processors. Lets use some enum type as a keys of this map:
enum class ActionType {
UPDATE,
DELETE,
ADD
}
private var map = mutableMapOf<ActionType, IMessageProcessor<IMessagePayload>>()
map[ActionType.ADD] = ProcessorImpl() // <-- error here
And that's where the problem occurs. I cannot put my ProcessorImpl into this map. The compiler says that there is an error: Type mismatch. Required: IMessageProcessor. Found: ProcessorImpl().
I could declare the map in the following way (using star projection):
private var map = mutableMapOf<ActionType, IMessageProcessor<*>>()
But in this case I cannot call processors's process method fetching it from the map by key first:
map[ActionType.ADD]?.process(Message("message-id", IdPayload(1))) // <-- error here
Compiler complains: Type mismatch. Required nothing. Found Message<IdPayload>
What am I doing wrong? Any help is appreciated.
This is about variance.
IMessageProcessor is defined as interface IMessageProcessor<T : IMessagePayload>; it has one type parameter, which must be IMessagePayload or a subtype.
But it is invariant in that type parameter; an IMessageProcessor< IdPayload> is not related to an IMessageProcessor<IMessagePayload>.  In particular, it's not a subtype.
And your map is defined with a value type IMessageProcessor<IMessagePayload>.  So its value cannot be an IMessageProcessor< IdPayload>, because that's neither the value type, nor a subtype.  Hence the compile error.
In this case, the simplest way to get it to compile is to change your map:
private var map = mutableMapOf<ActionType, IMessageProcessor<out IMessagePayload>>()
The only difference there is the out; that tells the compiler that the value IMessageProcessor is covariant in its type parameter.  (It may help to think of out as meaning ‘…or any subtype’.  Similarly, you could make it contravariant by using in, which you might think of as ‘…or any supertype’.)
This lets you store in the map an IMessageProcessor for any subtype of IMessagePayload.
However, if you do that, you'll find that you can't use any value you pull out of your map — because it can't tell which messages the processor can handle, i.e. which subtype of IMessagePayload it works for!  (The compiler expresses this as expecting a type parameter of Nothing.)
In general, it's often better to specify variance on the interface or superclass itself (declaration-site variance) rather than the use-site variance shown above.  But I can't see a good way to do that here, because you have multiple generic classes, and they interact in a complicated way…)
Think for a moment what IMessageProcessor's type parameter means: it's the type of message that the processor can consume. So an IMessageProcessor<A> can handle messages of type Message<A>.
Now, a subtype must be able to do everything its supertype can do (and usually more) — otherwise you can't drop that subtype anywhere that's expecting to use the supertype.  (That has the grand name of the Liskov substitution principle — but it's really just common sense.)
So an IMessageProcessor<B> is a subtype of IMessageProcessor<A> only if it can handle at least all the messages that an IMessageProcessor<A> can.  This means it must accept all messages of type Message<A>.
But Message is invariant in its type parameter: a Message<B> is not directly related to a Message<A>.  So you can't write a processor that handles them both.
The most natural solution I can find is to specify variance on both Message and IMessageProcessor:
data class Message<out T : IMessagePayload>( /*…*/ )
interface IMessageProcessor<in T : IMessagePayload> { /*…*/ }
And then use a wildcard in your map to make it explicit that you don't know anything about the type parameters of its values:
private var map = mutableMapOf<ActionType, IMessageProcessor<*>>()
That lets you safely store a ProcessorImpl() in the map.
But you still have to use an (unchecked) cast on the values you pull out of the map before you can use them:
(map[ActionType.ADD] as IMessageProcessor<IdPayload>)
.process(Message("4", IdPayload(4L)))
I don't think there's any easy way around that, because the problem is inherent in having values which are processors that can handle only some (unknown) types of message.
I'm afraid the best thing would be to have a rethink about what these classes mean and how they should interact, and redesign accordingly.

Understanding generic parameters in an abstract class

In the Kotlin docs, they show how to include type parameters:
class Box<T>(t: T) {
var value = t
}
This is a simple example. But I've come across one that looks like this:
abstract class SomeAdapter<T, WH: SomeViewHolder>(private val viewModel: SomeModel<T>?) {
}
How do I interpret this? Do I interpret this as:
SomeAdapter takes two parameters when it's instantiated - a T and a WH. And the constructor takes a viewModel.
As you already referenced, this class has two generic types: T and WH. The latter does specify an upper bound SomeViewHolder which will only allow sub types of that upper bound to be used as the generic type WH.
Since your title goes:
Understanding generic parameters in an abstract class
the question at hand is: Would it be different (regarding the generic types) if SomeAdapter would not be abstract. The answer is: No.
In this particular example T can be Any? and WH can be any subclass of SomeAdapter or SomeAdapter itself (if SomeAdapter is not abstract).
The types of T and WH are fixed at compile time (see Type erasure).
So, you have to see generics like a variable for a type.

How to get KClass of generic classes like BaseResponse<Iterable<User>>

If I try to get
BaseResponse<Iterable<User>>::class
I get error error only classes are allowed on the left hand side of class literal. I have searched and still not found how to get generic classes's type in kotlin.
You can't -KClass can only describe the class BaseResponse, and you can get a KClass instance that does that with BaseResponse::class.
What you have however, BaseResponse<Iterable<User>>, is a concrete type, which you can be represented as a KType instance. KType instances can be created, for example, with the createType function. This would look something like this:
// User
val userType = User::class.createType()
// Iterable<User>
val iterableOfUserType = Iterable::class.createType(arguments = listOf(KTypeProjection.invariant(userType)))
// BaseResponse<Iterable<User>>
val responseType = BaseResponse::class.createType(arguments = listOf(KTypeProjection.invariant(iterableOfUserType)))
I made the choice of making the type parameters both invariant, there's also factory methods in KTypeProjection to create covariant or contravariant types, as you need them.

How to put class dynamically in <>

I know there are various capabilities in Java with reflection.
For example:
Class<?> clazz = Class.forName("java.util.Date");
Object ins = clazz.newInstance();
I wonder if I could pass class dynamicaly in some method declaration in <> tags (or there is other way to do it if it must be fixed). I would like to change that class declaration dynamicaly; because I would like to write generic method for all types of classes.
In there, I have this:
List<Country>
Can I write it something diffrent with reflection? For example can it be somehow be achieved to pass class as parameter (or how else should be this done):
List<ins>
? I would appreciate examples.
This cannot be done because generics are a compile time feature. Once code is compiled, the only place where generics are exists are at method signatures, and they are only used for compiling new code.
When working with reflection, you are basicly working with raw types, and need to code according to that, that means, you can cast the returned result of newInstance() to the list type your need, for example:
List<Country> ins = (List<Country>)clazz.newInstance();
This is a safe operation to do, because you know at that point its empty, and isn't passed to any outside code.
I don't think this is possible. Generics in Java are implemented in a way that prohibits runtime access.
Generics are there so that the compiler can verify correct typing, but are no longer present at runtime (this is called "type erasure"). Reflection deals with the runtime representation of types only. As far as I know the only case where reflection has to deal with generics is to find out "fixed" type parameters of sub-classes, e.g. when you have class Bar<T> and class Foo extends Bar<String>, you can find out that the T of Bar is fixed to String in Foo using reflection. However, this is information found in the class file, too. Except that, reflection can only see or create raw-types.