Prevent Proguard obfuscating child classes with annotation - annotations

I have some class with Gson annotations that I need to keep from obfuscation via ProGuard. This bit of code works
public abstract class FacebookIdentifier {
#Expose public String id;
#Expose public String name;
}
-keepclasseswithmembers class * {
#com.google.gson.annotations.* <fields>;
}
Now I have some classes that extend such classes with no extra field. Example:
class FacebookApplication extends FacebookIdentifier {}
Such a class is obfuscated even though its parent has some annotations that prevent it from being obfuscated. Is there a way to have this class not being obfuscated ?

You would have to specify the extension explicitly:
-keep class com.example.FacebookApplication
However, for JSON, the class names probably don't matter; only the field names. Preserving the fields should be sufficient:
-keepclassmembers class * {
#com.google.gson.annotations.* <fields>;
}
This is assuming that all serialized fields are annotated, which is not strictly required for GSON.

Related

How to handle interface from graphql schema in java pojo

I have to create pojos from graphql schema file into java. like for
type Student{
name:String
age:Int
}
i created pojo
class Student{
private String name;
private int age;
// setter and getters
}
how to handle interface in java classes like
interface prop{
alttext: String
description: String
linkurl: String
title: String
}
I am writing a work around for my question, might be best solution is some thing else-
i created abstract class in java from interface of graphql schema. like below -
public abstract class prop {
private String alttext;
private String description;
private String linkurl;
private String title;
}
and for class extending this abstract class use super in constructor in child class to initialized abstract class members.

MapStruct equivalent of hint(Dozer)?

In Dozer we are able to mention interfaces in hint during field mapping. How can we achieve the same in MapStruct ?
I could not put the exact code here. But, it is the similar as below.
We have here an Domain class example:
Class A<T extends B> extends C<T>
{
...
};
Where,
B is a abstract class.
C is a class which contains a List item which we have to map.
Similar is the structure of the classes and interfaces on DTO side.
So, the mapping is as below in Dozer:
<mapping>
<class-a>Domain.A</class-a>
<class-b>DTO.A</class-b>
<field>
<a>item</a>
<b>item</b>
<a-hint>Domain.B</a-hint>
<b-hint>DTO.B</b-hint>
</field>
</mapping>
In MapStruct how do we refer the interfaces as given in the hint in Dozer ?
Scenario:
We have:
public class ShopList<T extends Inp> extends Shop<T>\
{ ... };
where,
Inp is a abstract class with no fields in it like:
public abstract class Inp() { };
Shop is a class like:
public class Shop<T extends ShopInp> implements Serializbale
{ private List<T> items = new ArrayList<T>();
//getters and setters for the items };
ShopInp is a public interface with no fields in it like:
public interface ShopInp {} .
We have similar structure of classes on DTO side and Domain side.
Could you please let me know how would the mapper look like for the above scenario ?
In general, If we try mapping the ShopList class, then, how do we ensure that the T extends ShopInp and T extends Inp are also being mapped as a part of ShopList?
So called hints can be used via BeanMapping#resultType. MapStruct can use that to create the instance of the object you are trying to map. However, it will only create mapping for the elements of the abstract class, as it has no other information during compilation time (Dozer uses reflection and can detect the fields of the type during runtime).
Imagine you have this structure
public interface Fruit {
String getName();
String setName(String name);
}
public Apple implements Fruit {
...
}
public Banana implements Fruit {
...
}
public abstract class FruitDto {
private String name;
//getters and setters
}
public AppleDto extends FruitDto {
...
}
public BananaDto extends FruitDto {
...
}
public class Basket {
private Collection<Fruit> fruits;
}
public class BasketDto {
private Collection<FruitDto> fruits;
}
Your mapper can then look like:
#Mapper
public interface BasketMapper {
BasketDto map(Basket basket);
#BeanMapping(resultType = BananaDto.class)
FruitDto map(Fruit fruit);
}
Using this mapper all fruits in the BasketDto would be of an instance BananaDto (due to the BeanMapping#resultType and mapping would only be created for the elements of the FruitDto

createLink to rest controllers

I have defined my domain objects
class Product implements Serializable{
String sku
static hasMany = [images: MediaContent]
}
class MediaContent implements Serializable{
[...]
}
and their REST controllers that extends RestFulController. In particular, the ProductRestController is as follows:
class ProductRestController extends RestfulController {
static responseFormats = ['json']
ProductRestController(){
super(Product)
JSON.registerObjectMarshaller(Product){
return [
id: it.id,
media: createLink(controller:"mediaRest", id:it.imageId)
]
}
The url mapping is very simple as
"/rest/product" (resources:"productRest")
"/rest/media" (resources:"mediaRest")
The issue is that the generated link with createLink directive is not in the rest format /rest/media/1 but /rest/media/index?id=1.
Both of these urls work, when invoked, but only the ?id= version is generated.
I have tried also createLink with resource property, but nothing works.
How could I achieve that?
You can make change in UrlMappings.groovy
"/rest/product/$action/$id"(controller: 'productRest')
"/rest/media/$action/$id"(controller: 'mediaRest')

how to inject a uiBinder with #Inject (instead of GWT.create())?

Firstly, is doing such thing a good practice ?
I tried what seems to be the right way for me but wasn't successful :
public class FormViewImpl extends CompositeView implements HasUiHandlers<C>, FormView {
public interface SettlementInstructionsSearchFormViewUiBinder extends UiBinder<Widget, SettlementInstructionsSearchFormViewImpl> {}
#Inject
static FormViewImpl uiBinder;
#Inject
static Provider<DateEditorWidget> dateEditorProvider;
#UiField(provided = true)
MyComponent<String> myComp;
#UiField
DateEditorWidget effectiveDateFrom;
// .. other fields
#Inject
public FormViewImpl () {
myComp = new MyComponent<String>("lol");
if (uiBinder == null)
uiBinder = GWT.create(SettlementInstructionsSearchFormViewUiBinder.class);
initWidget(uiBinder.createAndBindUi(this));
}
#UiFactory
DateEditorWidget createDateEditor() {
return dateEditorProvider.get();
}
}
What other things than a class with no arguments is required ? In my company's project the same kind of code works at some other place. Sorry from the high level of noob here...
If you guys had any pointers it would be nice.
Thanks
Two issues:
First, two of your #Inject fields are static - have you done anything to make static fields be injected? Static fields don't get set when Gin (or Guice) creates new instances, those have to be set once and done. As they are static, they will never be garbage collected - this may be okay with you, or it might be a problem, and you should change them to instance fields. If you want to keep them static, then you must invoke requestStaticInjection in your module to ask Gin to initialize them when the ginjector is created.
Next, if you do choose to remove static, the uiBinder field must still be null in that constructor, because the fields can't have been injected yet! How do you set a field on an object that you haven't yet created? That's what you are expecting Gin to be able to do. Instead, consider passing that as an argument into the #Inject decorated constructor. You don't even need to save it as a field, since the widget will only use it the one time.
To have a class generated by GIN (doesn't matter if it is a uiBinder or not) it is not necessary for it to have a default constructor (i.e. the one without parameters). The class you want to inject must have the constructor annotated with #Inject:
#Inject
public InjectMeClass(Object a, Object b)
The other class which is injected, suppose it is a UiBinder, must have the injected fields annotated with #UiField(provided=true):
public class Injected extends Composite {
private static InjectedUiBinder uiBinder = GWT
.create(InjectedUiBinder.class);
interface InjectedUiBinder extends UiBinder<Widget, Injected> {
}
#UiField(provided=true)
InjectMeClass imc;
public Injected(final InjectMeClass imc) {
this.imc=imc;
initWidget(uiBinder.createAndBindUi(this));
}
So, back to your case:
#UiField(provided = true)
MyComponent<String> myComp;
#Inject
public FormViewImpl (MyComponent<String> myComp) {
this.myComp = myComp;
and for example:
public class MyComponent<T> extends Composite {
private T value;
#Inject
public MyComponent(T t) {
this.value = t;
...
}
...
}
In the GIN module you can have a provider:
#Provides
#Singleton
public MyComponent<String> createMyComponent() {
return new MyComponent<String>("lol");
}

I cannot serialize a sub class that is cast to its base class over GWT

I am having trouble serializing an object over GWT that contains a sub class that is cast to its base class. My class hierarchy is as follows:
public class BaseManagedObject implements IsSerializable
{
public Shortcut getShortcut()
{
return new Shortcut();
}
}
public class User extends BaseManagedObject implements IsSerializable
{
public Shortcut getShortcut()
{
return new DomainMemberShortcut();
}
}
public class Shortcut implements IsSerializeable {}
public class DomainMemberShortcut extends Shortcut implements IsSerializable {}
When I serialize a User object, I get "The response could not be deserialized". If I change User to return a Shortcut in getShortcut(), there is no problem. I added code that references the DomainMemberShortcut, just to verify that I can build with it, and that works fine.
Any suggestions?
Thanks,
Found the solution - I was missing the default no-arg constructor in the DomainMember subclass.