JAXB Generic XmlAdapter implementation - java

This question continues my previous thread : here
Now i want to use a generic XmlAdapter, because i need to apply the same work on differents type of value. I can create one class per type, but that's not the purpose of my question, i want to make this generic. So this is what i did :
Generic Adapter Class
public class GenericXMLAdapter<T> extends XmlAdapter<GenericXMLAdapter.AdaptedValue<T>, T>{
public static class AdaptedValue<T> {
#XmlAttribute
public T code;
}
#Override
public T unmarshal(AdaptedValue<T> v) throws Exception {
return v.code;
}
#Override
public AdaptedValue<T> marshal(T v) throws Exception {
AdaptedValue<T> adaptedValue = new AdaptedValue<T>();
adaptedValue.code = v;
return adaptedValue;
}
}
My temporary class to generate the correct Adapter
public final class DefinedXMLAdapter {
public static class BooleanAdapter extends GenericXMLAdapter<Boolean> {};
}
Example to marshall
#XmlElement(name = "theBoolean")
#XmlJavaTypeAdapter(DefinedXMLAdapter.BooleanAdapter.class)
protected Boolean myBoolean = false;
When i execute my code, i get a weird error i can't understand :
Exception in thread "main" java.lang.NullPointerException
at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor.get(TransducedAccessor.java:154)
...
Can someone explains to me what's wrong with my code and how to resolve this issue ?

I finally managed to solve my problem by using MOXy as the JAXB implementation.
Thanks for your time, have a good day!

Related

Annotation Arguments with Generics Class

I would like to understand of this issue
public class DogController extends FeedCommonController<DogModel extends CommonAnimalModel, FARMER_1_AUTH> {
// something
// This is working - but there is duplication
#Security.Authenticated(FARMER_1_AUTH.class)
public boolean feed_it() {
// nothing special
DogModel.getRandom().feed_it();
}
}
public class CatController extends FeedCommonController<CatModel extends CommonAnimalModel, FARMER_2_AUTH> {
// something
// This is working - but there is duplication
#Security.Authenticated(FARMER_2_AUTH.class)
public boolean feed_it() {
// nothing special
CatModel.getRandom().feed_it();
}
}
And I want to simplify the code and remove the duplicate methods, but I cannot put Class type to annotation.
public abstract class CommonAnimalController< T extends CommonAnimalModel, XXXXXX> {
#Security.Authenticated(XXXXXX.class) // <-- Here is a problem with declaration
public boolean feed_it() {
T.getRandom().feed_it();
}
}
/**
Get Token From HTTP Request from Actual Thread
*/
public class Security {
#With(AuthenticatedAction.class)
#Target({ElementType.TYPE, ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface Authenticated {
Class<? extends Authenticator> value() default Authenticator.class;
}
}
Concept with Annotation is already created and implemented on hundred classes. So its not possible make huge changes. But Its some Elegant way how to solved this?
You have two problems in one question.
First problem you have is: How to get a class instance of generics type T
This is answered here: How to get a class instance of generics type T
The second problem you have, is how to avoid passing a constant to the annotation. You will have a compliation error "Attribute value must be constant"
For this second problem seems there is no simple way to achieve it in Java. (pheraps I am wrong)
See this answer: How to supply value to an annotation from a Constant java
Solution for problem1
public abstract class CommonAnimalController<T extends CommonAnimalModel, XXXXXX> {
final Class<XXXXXX> typeParameterClass;
public CommonAnimalController(Class<XXXXXX> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}
#Security.Authenticated(typeParameterClass) // you will have "Attribute value must be constant"
public boolean feed_it() {
return T.getRandom().feed_it();
}
}

Using a Class with Generics with GSON

I am hoping to get some direction on how to resolve this issue. I am working with a Third Party API get JSON data. It has a structure similar to:
{items: [
{attribute : Value},
{attribute : Value}]
count : value,
etc
}
The items array can hold different data, so I have a class:
public Items<T> {
private List<T> items;
// Others API Variables
public List<T> getItems(){
return items;
}
public void setItems(List<T> items){
this.items = items;
}
// Other Getters/Setters
}
What I am trying to do in the calling class is:
public CallingClass {
public void Method(){
//Code to get reader object
Items<User> userItems = Gson().fromJson(ReaderObject, Items.class);
//Other processing code
}
}
And I get the error:
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to User.class
I was reading through this post and I think the solution is similar to what I need but I don't know who to do it. My though was to have a single Items class that could be passed the different Types which are returned.
Thoughts, assistance, anything would be helpful.
EDIT:
OK So I feel like an idiot now, but some sleep helped. The solution was in the link I posted, I was just didn't need a list. My coded solution is as follows:
public CallingClass {
public void Method(){
//Code to get reader object
Items<User> userItems = Gson().fromJson(ReaderObject, new TypeToken<Items<User>>(){}.getType());
//Other processing code
}
}
OK So I feel like an idiot now, but some sleep helped. The solution was in the link I posted, I was just didn't need a list. My coded solution is as follows:
public CallingClass {
public void Method(){
//Code to get reader object
Items<User> userItems = Gson().fromJson(ReaderObject, new TypeToken<Items<User>>(){}.getType());
//Other processing code
}
}

Unchecked cast warning with abstract method providing specific return value

I'm writing selenium tests for an app that has very standard pages that can easily be modeled by a generic structure as the base for the pages, with only a few base types (mostly list pages containing a list of records, and edit pages where one can edit one record). To model this I have these two classes:
public abstract class AbstractListPage<E extends EditPage> extends AbstractSelfOpeningPage implements ListPage {
// Provides the specific object for the edit page when it's opened
protected abstract E editPageHook();
public E getEditPage() {
return editPageHook();
}
public E openEditPage(String key, boolean search) {
//Do page opening stuff like clicking buttons
// Return new object for the page that has been opened
return getEditPage();
}
}
// Implementation class
public class DossiersListPage extends AbstractListPage<DossierPage> {
#Override
protected DossierPage<DossiersListPage> editPageHook() {
return new DossierPage<>(driver, this);
}
}
// Usage in test, this shows an unchecked cast warning
DossierPage<DossiersListPage> dossierPage = new DossiersListPage(driver).openPage().openEditPage("3905");
I would like to know if there is a good way to fix this, and what am I missing? I'm not having any issues currently, but the warning all over my test code is making me feel a bit iffy.
The reason for the generics here is so I can model elements on my page that return the page they belong to in a fluent way:
public abstract class AbstractPageElement<P extends Page> implements PageElement<P> {
#Override
public P click() throws TimeoutException {
// Do click
return page;
}
}
// DossierPage
public class DossierPage<L extends ListPage> extends AbstractEditPage<L> {
public OrderDate<DossierPage<L>> orderDate = new OrderDate<>(driver, this);
public OrderType<DossierPage<L>> orderType = new OrderType<>(driver, this);
public Status<DossierPage<L>> status = new Status<>(driver, this);
}
// Test
dossierPage.orderDate.click()
.orderType.click()
.status.click();
I could reverse-engineer the problem. The DossierPage must look something like this:
public class DossierPage<E extends AbstractListPage> extends EditPage {
//...
}
So now we're getting the problem. You can solve it by specifying more type arguments:
public class DossiersListPage extends
AbstractListPage<DossierPage<DossiersListPage>> { // this is the tricky part
#Override
protected DossierPage<DossiersListPage> editPageHook() {
return new DossierPage<>();
}
//...
}
Just add the following line above the line giving the warning:
#SuppressWarnings("unchecked")

Subclassing a ParseObject Subclass (Android)

Is it possible to subclass subclasses of ParseObjects? I am following the directions here. My class looks like this:
#ParseClassName("Stove")
public class Stove extends ParseObject{
private String URL = "url";
private String BRAND_NAME = "brand name";
public Stove() {
//Needed for Parse
}
public Stove(String url, String brandName) {
put(URL, url);
put(BRAND_NAME, brandName);
}
public String getUrl() {
return getString(URL);
}
public String getBrandName() {
return getString(BRAND_NAME);
}
...
}
and I have a subclass of this that looks like
#ParseClassName("ElectricStove")
public class ElectricStove extends Stove{
public ElectricStove() {
}
public ElectricStove(String url, String brandName) {
super(url, brandName);
}
...
}
My Application subclass is registered in AndroidManifest.xml and has this code in onCreate():
ParseObject.registerSubclass(Stove.class);
ParseObject.registerSubclass(ElectricStove.class);
...
Parse.initialize(this, "<lots of letters>", "<more letters>");
ParseInstallation.getCurrentInstallation().saveInBackground();
I'm getting this exception
Caused by: java.lang.IllegalArgumentException: You must register this ParseObject subclass before instantiating it.
at com.parse.ParseObject.<init>(ParseObject.java:363)
at com.parse.ParseObject.<init>(ParseObject.java:324)
at <package>.Stove.<init>(Stove.java:16)
at <package>.ElectricStove.<init>(ElectricStove.java:7)
which makes me wonder if I'm going about this in the wrong way or if it's perhaps simply not possible.
It's just not possible at this point, as Parse Android SDK does not support this. Rather, as a suggestion, use an identifier to specify what type of "Stove" a particular stove object is. Take this example:
#ParseClassName("Instrument")
public class Instrument extends ParseObject {
public Instrument() {
// A default constructor is required.
}
public InstrumentType getType() {
return InstrumentType.parse(getString("type"));
}
public void setType(InstrumentType type) {
put("type", type.toString());
}
then use:
final Instrument ocarina = new Instrument();
// Since our Instruments are strongly-typed, we can provide mutators that only take
// specific types, such as Strings, ParseUsers, or enum types.
ocarina.setType(InstrumentType.WOODWIND);
This would be a work-around of sorts to allow you to perform actions on an object based on it's type. It's not perfect, but it may suit your needs. The InstrumentType is just a class used for static constants in order to access id values
Example taken from here

Java Generics Question

Alright, I thought I understood generics pretty well, but for some reason I can't get my head wrapped around why this doesn't work. I have two classes, or I should say that Google has two classes (I'm trying to implement their Contacts API). They have a ContactEntry class (abbreviated below):
package com.google.gdata.data.contacts;
public class ContactEntry extends BasePersonEntry<ContactEntry> {
public ContactEntry() {
super();
getCategories().add(CATEGORY);
}
public ContactEntry(BaseEntry<?> sourceEntry) {
super(sourceEntry);
}
}
I left off one or two methods, but nothing important, its really just an implementation of its parent class BasePersonEntry which has most of the important stuff that concerns a person entry abbreviated code below:
package com.google.gdata.data.contacts;
public abstract class BasePersonEntry<E extends BasePersonEntry> extends
BaseEntry<E> {
public BasePersonEntry() {
super();
}
public BasePersonEntry(BaseEntry<?> sourceEntry) {
super(sourceEntry);
}
public List<CalendarLink> getCalendarLinks() {
return getRepeatingExtension(CalendarLink.class);
}
public void addCalendarLink(CalendarLink calendarLink) {
getCalendarLinks().add(calendarLink);
}
public boolean hasCalendarLinks() {
return hasRepeatingExtension(CalendarLink.class);
}
}
Now... what I can't quite understand is if I do something like the following:
public void method1(StringBuilder sb, ContactEntry contact) {
if (contact.hasCalendarLinks()) {
for (CalendarLink calendarLink : contact.getCalendarLinks()) {
...
}
}
}
Everything works fine. It is able to interpret that getCalendarLinks returns a list of type CalendarLink. However, if I want to abstract this method and have my method use BasePersonEntry, like the following:
public void method1(StringBuilder sb, BasePersonEntry entry) {
if (entry.hasCalendarLinks()) {
for (CalendarLink calendarLink : entry.getCalendarLinks()) {
...
}
}
}
I get a compiler error:
incompatible types
found : java.lang.Object
required: com.google.gdata.data.contacts.CalendarLink
For the life of me I just can't understand why? The call to getCalendarLinks is the EXACT same method (via inheritance), its returning the EXACT same thing. Maybe it has to do with BasePersonEntry being an abstract class?
If anyone, can shed some light on this I would be very much obliged. If it helps you can find a full version of this source code hosted by Google here: Link To Google Library Download. I was attempting this with version 1.41.3 of their gdata-java libraries.
The problem with your new definition, is that it's using Raw type not Generic type.
As a result type is erased from everything, including getCalendarLinks and its signature is reduced to equivalent of List<Object> getCalendarLinks( )
To fix it, change declaration to:
public void method1(StringBuilder sb, BasePersonEntry<?> entry)
Note <?> after BasePersonEntry. This way it's generic type.
Also, you probably want to change the class generic declaration to
public abstract class BasePersonEntry<E extends BasePersonEntry<E> >
Without <E> your compiler ( or IDE ) will generate an unchecked warning.

Categories

Resources