Can you rename a variable in a generic Class? - java

I have got a Class PagedResult. The class is there to help me realize a JSON output with different objects in a pages format. The E is the object, that is wrapped in the List. It works all fine, but one thing still bothers me. I would like that the list with the objects does not always get the same name. I would like to adapt the name to the corresponding objects.
Class PagedResult:
public class PagedResult<E> {
Long totalItems;
Integer totalPages;
Integer currentPage;
List<E> elements;
[... Getter & Setter ...]
}
The actual JSON Output with an Object like MyPojo looks like this:
{
"totalItems": 2,
"totalPages": 1,
"currentPage": 1,
"elements": [
{
"myPojoAttr1": "hello",
"myPojoAttr2": "there"
},
{
"myPojoAttr1": "hello",
"myPojoAttr2": "folks"
}
]
}
So for each response, no matter which objects, the array is namend as "elements". I don´t want the ugly name in my JSON response, because of the changing objects in the PagedResult-class. When I get a response with objects like MyPojo the name of the JSON-Array should be "myPojos" and when I want to get a response with objects like MyWin the name "myWins".
I tried alot with #JsonProperty, but I can´t find a way, to do this "object-array-name" also generic. Can someone assist me with the problem please? Thanks in advance.

No. You can't do that. Generic types have parameters for types, not for identifiers. AFAIK, nothing in the Java language allows you to treat a Java identifier as a parameter when producing a type. (Certainly, nothing you could use in this context!)
Alternatives:
Don't do it. (Take a good hard look at your reasons for wanting the JSON attribute name to vary. What does it actually achieve? Is it worth the effort?)
Don't use a generic type. Define a different class for each kind of "paged result". (Clunky. Not recommended.)
Use a map, and populate it with a different map key for the elements attribute of each kind of "paged result". (The disadvantage is that you lose static type checking, and take a small performance and storage penalty. But these are unlikely to be significant.)
Write a custom mapper to serialize and deserialize the PagedResult as per your requirements.
For what it is worth, identifiers as parameters is the kind of thing you could do with a macro pre-processor. That Java language doesn't have standard support for that kind of thing.

Yes it's possible, using custom serializers. But even with a custom serializer you still have a problem: Generics are removed at compile time. So we need to somehow get the type during runtime.
Here is an example that will just check the type of the first element in the elements list. Definietly not the cleanest way to do it, but you don't have to adjust your PagedResult class.
public class PagedResultSerializer<T> extends JsonSerializer<PagedResult<Object>> {
#Override
public void serialize(PagedResult<Object> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeNumberField("totalItems", value.getTotalItems());
// Your other attributes
if (!value.getElements().isEmpty()) {
Object firstElement = value.getElements().get(0);
String elementsFieldName;
if (firstElement instanceof MyPojo) {
elementsFieldName = "myPojos";
} else if (firstElement instanceof MyWin) {
elementsFieldName = "myWins";
} else {
throw new IllegalArumentException("Unknown type");
}
serializers.defaultSerializeField(elementsFieldName, value.getElements(), gen);
}
gen.writeEndObject();
}
}
Now you just need to tell Jackson to use this serializer instead of the default one.
#JsonSerialize(using = PagedResultSerializer.class)
public class PagedResult<T> {
// Your code
}
Improvments: Add a Class<T> elementsType attribute to your PagedResult and use this attribute in your serializer instead of checking the first element in the list.

Another approach: use inheritance.
Have an abstract base class PagedResult that contains all the common fields, to then distinctively subclass it to PagedResultWithElements, PagedResultWithMyPojo and so on. And the subclasses contain just that "type" specific list.
As a drawback: you get some code duplication. But on the other side, you get quite more control over what happens without doing overly complicated (de)serialization based on custom code.
So, when you know the different flavors of "element types", and we talk say 3, max 5 different classes, using inheritance might be a viable solution.

Related

DesignPattern: Partial Object creation of unknown instance members at runtime

Currently I have an endpoint which returns a a fairly large data object.
This call for all objects of that type can generate 20MBs of data. However not always the clients need all the information in the object, quite often a subset of data is all that is required. I want to give the client the option to pass in some parameters to determine what parts of the object they require.
For example, specifying an array of restriction fields with each field itself a group of instance members on the object, a user can restict how much f the object they want. Looking at the figure Object below, restriction field value r1 may refer to instance members a and b.
example request "myurl/restrict=r1,r2"
MyObject(){
a;
b;
c;
d;
e;
f;
g;
h;
.... many more fields
}
So with that in mind, I created an ENUM to model the restriction fields and the subset of instance members which each instance field represents.
Now on the DB query I want to use the ENUM(s) values to decide which parts of the object I want.
So the select query will select the Object and the object can be partially instantiated by calling whatever get/set methods are required. I have implemented this on the query side by using the request params(i.e. groupings of instance members) and performing reflection on the object returned from the DB to get/set the instance fields on the object to return.
I am however, unsure if there is an already existing design pattern for this problem other than a refactor or create a new endpoints for the "lighter" objects. I dont want to argue that case, I just want to discuss for the problem at hand, is reflection a valid method of fulfilling the requirement and if not why not and what are the alternatives.
I believe this solution can cater for change easily, Only the enum needs updated if instance members change or a restriction grouping needs adapting. The rest layer or data layer requires no change. However I am unsure of the performance impact, i only implemented this today so I haven't been able to benchmark yet.
I guess the real question is; is there a design pattern for partial object creation of unknown member fields at runtime
Below is psuedo of how i implemented the select aspect below.
select(MyObj obj){
//get all the restricted fields from the request
// Instantiate new object
// for each restriction field(i.e. instance member)
// use reflection to invoke the set method of the new object(partial) passing the get method of the method argument(full object)
}
You can use object mapper for that
Employee -> name , id, uid, address
Using objectmapper readvaluetotree
Returns JsonNode/ObjectNode
Select your keys to construct the new json
Json= { "name": "xyz", "id": 101, "uid": "xoz", "address": "xqp street" }
Delete the keys which you don't need using
jsonNode.remove or delete key
then use the jsonNode to parse back to object
Employee em = objectmapper.readValue( json, Employee.class)
I think I may have found a really nice method for this task leveraging the functional aspect of Java8. Indeed this could also be implemented using an anonymous class pre Java8.
I can make use of this in the Enum and construct each one with a BiConsumer.
I can then implement that copy method while I iterate through the passed in arguments.
Now I have have the behaviour I had with reflection but without the performance impact.
public enum RestrictFields {
R1((source, target) -> {
target.setA(source.getA());
target.setB(source.getB());
target.setC(source.getC());
}),
R2((source, target) -> {
target.setD(source.D());
});
private final BiConsumer<MyObj, MyObj> copier;
private RestrictFields (final BiConsumer<MyObj, MyObj> copier) {
this.copier = copier;
}
public void copy(final MyObj source, final MyObj target){
this.copier.accept(source, target);
}
}
Now when in the select clause I can cycle through the passed Enum Values and invoke the copy method and build the restricted object based on that.
public Object select(MyObj source) {
MyObj myobj = new MyObj ();
if (!restrictedFields.isEmpty()) {
// Instead of refelction here I can use the biconsumer in the enum
for (RestrictFields field : restrictedFields) {
field.copy(source, myobj);
}
return myObj;
}
return source;
}

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.

ObjectMapper using TypeReference not working when passed type in generic method

This is the method:
protected <T> TestPageResult<T> getTestPageResutForRequest(MockHttpServletRequestBuilder request) throws Exception {
String responseJson = mockMvc.perform(request).andReturn().getResponse()
.getContentAsString();
TestPageResult<T> response = getObjectMapper().readValue(responseJson,
new TypeReference<TestPageResult<T>>() {
});
return response;
}
I call it like this:
TestPageResult<SomeDto> pageResult = this.<SomeDto>getTestPageResutForRequest(getRequest());
TestPageResult is:
protected static class TestPageResult<T> {
private List<T> items;
private long totalCount = -1;
public TestPageResult() {
}
//omitted getters and setters
}
The resulting pageResult.getItems() contains a List of LinkedHashMap instead of a list of SomeDto. If I were to just hardcode the SomeDto type in the objectMapper.readValue method I'd get the correct results.
What's the problem?
edit: The suggested duplicated did solve my problem - kind of.
I used:
JavaType type = getObjectMapper().getTypeFactory().constructParametricType(TestPageResult.class, clazz);
TestPageResult<T> response = getObjectMapper().readValue(responseJson, type);
Problem is there is no going around not passing down a Class argument to the method. So the method looks ugly due to both passing a generic type and the same thing as a Class. Obviously you can just not pass the generic now but this way a casting would be required and adding SuppressWarnings and so on.
The problem is erasure. All these <T> parameters don't exist in the compiled code, after they're erased. This means that source new TypeReference<TestPageResult<T>>() looks like new TypeReference<TestPageResult>() once compiled, which is not what you want. (Similar to how a List<String> ends up being a List in compiled code, and it's just compile-time validation that you don't add Integers to your String List.)
I think there's roughly two ways to deal with this (in this case), both of these you already stumbled upon:
Either you create a type that properly represents what you want, such as: new TypeReference<TestPageResult<SomeDto>>(), or class SomeDtoPageResult extends TestPageResult<SomeDto> which you can then use in places like readValue(..., SomeDtoPageResult.class);
Or you create a complete class representation, like you were doing with JavaType
What you really want won't work. Your best bet is to tinker and come up with the cleanest code that solves it. Generics let you express really elaborate structures, and when you serialize an actual instance (nested objects), that comes out just fine, but when the classes need to be introspected at runtime, e.g. for deserialization (your use case) or to build a model (e.g. to generate Swagger docs), this becomes problematic.

how to read object attribute dynamically in java?

Is there any way to read and print the object attribute dynamically(Java) ? for example if I have following object
public class A{
int age ;
String name;
float income;
}
public class B{
int age;
String name;
}
public class mainA{
A obj1 = new A();
method(A);
method(B);
}
the output should be like
While running method(A):
Attribute of Object are age,name,income;
While executing method(B):
Attribute of Objects are age,name;
My question is I can pass various object in method(), is there any way I can access the attribute of the differnt object in general.
You want to use The Reflection API. Specifically, take a look at discovering class members.
You could do something like the following:
public void showFields(Object o) {
Class<?> clazz = o.getClass();
for(Field field : clazz.getDeclaredFields()) {
//you can also use .toGenericString() instead of .getName(). This will
//give you the type information as well.
System.out.println(field.getName());
}
}
I just wanted to add a cautionary note that you normally don't need to do anything like this and for most things you probably shouldn't. Reflection can make the code hard to maintain and read. Of course there are specific cases when you would want to use Reflection, but those relatively rare.
Using org.apache.commons.beanutils.PropertyUtils we can do this. If the proper getters and setters are defined for the bean we can also dynamically set the value:
import org.apache.commons.beanutils.PropertyUtils;
import java.beans.PropertyDescriptor;
public class PropertyDescriptorTest {
public static void main(String[] args) {
// Declaring and setting values on the object
AnyObject anObject = new AnyObject();
anObject.setIntProperty(1);
anObject.setLongProperty(234L);
anObject.setStrProperty("string value");
// Getting the PropertyDescriptors for the object
PropertyDescriptor[] objDescriptors = PropertyUtils.getPropertyDescriptors(anObject);
// Iterating through each of the PropertyDescriptors
for (PropertyDescriptor objDescriptor : objDescriptors) {
try {
String propertyName = objDescriptor.getName();
Object propType = PropertyUtils.getPropertyType(anObject, propertyName);
Object propValue = PropertyUtils.getProperty(anObject, propertyName);
// Printing the details
System.out.println("Property="+propertyName+", Type="+propType+", Value="+propValue);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
To set the value of a particular property:
// Here we have to make sure the value is
// of the same type as propertyName
PropertyUtils.setProperty(anObject, propertyName, value);
Output will be:
Property=class, Type=class java.lang.Class, Value=class genericTester.AnyObject
Property=intProperty, Type=int, Value=1
Property=longProperty, Type=class java.lang.Long, Value=234
Property=strProperty, Type=class java.lang.String, Value=string value
You can use reflection to get every field from your object (if security configuration allows you).
If you need it not for the sake of self-education, then it may be worth using ReflectionUtils from Apache Commons.
You can use reflection, but the API is not very nice to use. But what you are trying to do is not at all object-oriented. The A and B should have method "print yourself" which would output their values (you should specify the method in superclass/interface to call the method using polymorphism).
I think I would consider a different approach.
If you really want to treat these like data is there any reason they couldn't be hashtables (Do they have associated code)?
Reflection will do it but it's a last resort--you should always seriously consider different approaches before dropping to reflection.
Cases where you must access variables like that exist--like database mapping (Hibernate) and injection (Spring). You might want to consider if a packaged solution like that fits your need so that future programmers can understand what you did without learning everything about your specific solution.
Also, Spring injection can do things that might fit your needs.
Also also if you are going to use reflection, seriously consider annotations so that you aren't tying your functionality to what should be simple arbitrary attribute names.

Java type conversion where types are not known until runtime

I'm trying to write a data access layer for an AJAX web project. This DAL has to convert data coming in via an AJAX servlet to objects that can be passed to a PreparedStatement for execution.
Data in the AJAX servlet, retrieved by using HttpServletRequest.getParameter(...), come in as strings.
In each data class, I have a known set of fields as well as their data types, e.g. CustomerId(integer), CustomerName(string).
I can of course write a method in the Customer class to handle the conversion, but this means I have to do it for every data object's class. I would much rather have a generic method that does conversion, e.g.
Object convert(String value, Class<?> targetType) { ... }
Can anyone point me in the right direction?
Create an utility class with all conversion methods you would like to use. Inside its static initializer, make use of reflection to collect all those methods by parameter type and return type in a map. Then, in the convert() method just pick the method which suits the given source and target type and invoke it. Make use of generics to fix the return type to be the same as the target type:
public static <T> T convert(Object from, Class<T> to)
You can find an example in this article.
But as bmargulies pointed out, JSON is also an interesting option. You could let ajax to send all parameters as one JSON string. Then, you can use a JSON-to-Javabean converter like Google Gson to convert the JSON string to a fullworthy Javabean like Customer. It'll be as simple as:
String jsondata = request.getParameter("jsondata");
Customer customer = new Gson().fromJson(jsondata, Customer.class);
// ...
See also this answer for another example.
There are JSON libraries that will do data type conversion. Jackson is one. Or, you could code the whole think using a JAX-RS service framework instead of a raw servlet, and it will take care of all this for you. Apache CXF is one framework that contains this support. Since you are asking for a generic solution, why not use one that's already out there.
We do this exact thing using a plethora of static converters in a utility class. It isn't elegant but it sure is easy and effective.
class Util {
public static Long StringToLong(String s) { ... }
public static Integer StringToInt(String s) { ... }
public static Date StringToDate(String s) { ... }
public static Date StringToDateYYMMDD(String s) { ... }
public static BigDecimal StringToBigDecimal(String s) { ... }
// etc ad naseum
}
Since you want to use the parameters in your PreparedStatement, why do you have to convert them at all?
When using setString(index, parameter) SQL will be happy to do the conversion for you.
Thus the only thing you might want to do is some kind of validation that the input is really valid (or you could even leave this part to your SQL engine which will throw an exception if it doesn't understand you.

Categories

Resources