Does anyone have any workarounds for CheckStyle and StaticMetamodel (which totally set aside TypeName and getter/setter best practices.
#StaticMetamodel(Student.class)
public abstract class Student_ {
public static volatile SingularAttribute<Student, String> firstName;
public static volatile SingularAttribute<Student, String> lastName;
public static final String FIRST_NAME = "firstName";
public static final String LAST_NAME = "lastName";
}
Checkstyle warnings:
Name 'Student_' must match pattern '^[A-Z][a-zA-Z0-9]*$'. (8:20) [TypeName]
Variable 'firstName' must be private and have accessor methods. (11:75) [VisibilityModifier]
Variable 'lastName' must be private and have accessor methods. (15:77) [VisibilityModifier]
So one answer is to use these suppressions.
#SuppressWarnings({"checkstyle:typename", "checkstyle:visibilitymodifier"})
Note, you have to wire up suppressions correctly.
See this:
Ignoring of Checkstyle warnings with annotation #SuppressWarnings
Related
Serialization does not happen properly when I use #Json in the fields but it started working after changing to #field:Json.
I came through this change after reading some bug thread and I think this is specific to kotlin. I would like to know what difference does #field:Json bring and is it really specific to kotlin?
Whatever you put between # and : in your annotation specifies the exact target for your Annotation.
When using Kotlin with JVM there is a substantial number of things generated, therefore your Annotation could be put in many places. If you don't specify a target you're letting the Kotlin compiler choose where the Annotation should be put. When you specify the target -> you're in charge.
To better see the difference you should inspect the decompiled Java code of the Kotlin Bytecode in IntelliJ/Android Studio.
Example kotlin code:
class Example {
#ExampleAnnotation
val a: String = TODO()
#get:ExampleAnnotation
val b: String = TODO()
#field:ExampleAnnotation
val c: String = TODO()
}
Decompiled Java code:
public final class Example {
#NotNull
private final String a;
#NotNull
private final String b;
#ExampleAnnotation
#NotNull
private final String c;
/** #deprecated */
// $FF: synthetic method
#ExampleAnnotation
public static void a$annotations() {
}
#NotNull
public final String getA() {
return this.a;
}
#ExampleAnnotation
#NotNull
public final String getB() {
return this.b;
}
#NotNull
public final String getC() {
return this.c;
}
public Example() {
boolean var1 = false;
throw (Throwable)(new NotImplementedError((String)null, 1, (DefaultConstructorMarker)null));
}
}
For more info go to Kotlin docs.
I am working on an embedded jersey instance which will run a JAXB RESTful service. I have configured Jackson with two steps:
Adding this to my POM
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.23.2</version>
</dependency>
Registering it in my application
public HandheldApplication() {
scripts.add(HandheldServer.class);
scripts.add(BasicScript.class);
// Add JacksonFeature.
scripts.add(JacksonFeature.class);
scripts.add(LoggingFilter.class);
}
I have a complex object being passed back and forth as shown below:
package com.ziath.handheldserver.valueobjects;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.*;
#SuppressWarnings("restriction")
#XmlRootElement
public class Widget {
private String key;
private String name;
private List<String> options = new ArrayList<String>();
private String value;
private String type;
public Widget(){
super();
}
public Widget(String key, String name, List<String> options, String value,
String type) {
super();
this.key = key;
this.name = name;
this.options = options;
this.value = value;
this.type = type;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getOptions() {
return options;
}
public void setOptions(List<String> options) {
this.options = options;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
When I execute this in a GET method as shown below:
#Override
#GET
#Path("getKeys")
#Produces(MediaType.APPLICATION_JSON)
public List<Widget> getKeys(#QueryParam(value = "page") int page)
This works fine and I get JSON back; however when I execute it is a PUT as shown below:
#Override
#PUT
#Path("validateKeys")
#Produces({MediaType.APPLICATION_JSON})
#Consumes(MediaType.APPLICATION_JSON)
public boolean validateKeys(#QueryParam(value = "page")int page, #QueryParam(value = "widgets")List<Widget> widgets)
When I execute a PUT to access this method I get a stack trace as follows:
Caused by: org.glassfish.jersey.internal.inject.ExtractorException: Error un-marshalling JAXB object of type: class com.ziath.handheldserver.valueobjects.Widget.
at org.glassfish.jersey.jaxb.internal.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:195)
at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.convert(AbstractParamValueExtractor.java:139)
at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.fromString(AbstractParamValueExtractor.java:130)
at org.glassfish.jersey.server.internal.inject.CollectionExtractor.extract(CollectionExtractor.java:88)
at org.glassfish.jersey.server.internal.inject.CollectionExtractor$ListValueOf.extract(CollectionExtractor.java:107)
at org.glassfish.jersey.server.internal.inject.QueryParamValueFactoryProvider$QueryParamValueFactory.provide(QueryParamValueFactoryProvider.java:89)
... 38 more
Caused by: javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:563)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:249)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:140)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:123)
at org.glassfish.jersey.jaxb.internal.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:190)
... 43 more
So it seems to me that Jackson is correctly marshalling my POJO into JSON but trying to unmarshall it as XML. Note that I switched to Jackson away from MOXy because I needed to be able to handle collections coming back and forth and apparently MOXy cannot do that.
Is there a setting I've missed to tell Jackson/Jersey to go both ways for JSON?
Try removing #QueryParam(value = "widgets") because you should pass it as entity body - not query param.
#PUT
#Path("validateKeys")
#Produces({MediaType.APPLICATION_JSON})
#Consumes(MediaType.APPLICATION_JSON)
public boolean validateKeys(#QueryParam(value = "page")int page, List<Widget> widgets)
Also you can make wrapper class:
#XmlRootElement
public class Widgets {
private List<Widget> widgets;
// other fields, setters and getters
}
And then:
#PUT
#Path("validateKeys")
#Produces({MediaType.APPLICATION_JSON})
#Consumes(MediaType.APPLICATION_JSON)
public boolean validateKeys(#QueryParam(value = "page")int page, Widgets widgets)
I would suggest to read some discussions about REST design because you're using verbs in your paths:
Is this a bad REST URL?
Understanding REST: Verbs, error codes, and authentication
I was switching between QueryParam and FormParam to try and get one of them to work. If I use FormParam I also need to change the consumes to APPLICATION_FORM_URLENCODED.
The actual issue was that the default unmarshalling with Jackson was using XML because it was tagged as an XML resource - take that out! I finally managed to work out how to unmarshall from JSON by using a static fromString method. Then to handle the list; I cannot use a wrapper class because this needs to be highly cross language and exposing a wrapper with a list would have complicated the implementation from Python, C#, etc. The way to get it to accept a list with a wrapper is to post the name of the param (in this case widgets) multiple time. Then each JSON passed in will be called against the fromString method.
According to RestyGWT documentation one must use an abstract super class for this to work, for instance, given:
#JsonSubTypes(#Type(value=PersonImpl.class, name="PersonImpl"))
#JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="#class")
public abstract class Person{
public abstract String getName();
public abstract void setName(String name);
}
#JsonTypeName("PersonImpl")
public class PersonImpl extends Person{
private String name;
#Override
public final String getName() {
return name;
}
#Override
public final void setName(String name) {
this.name = name;
}
}
If I use the defined encoder/decoder this would work:
Person personInstance = new PersonImpl();
personInstance.setName("TestName");
PersonCodec codec = GWT.create(PersonCodec.class);
JSONValue json = codec.encode(personInstance);
Im trying to do something quite similar but with a small difference, that is, instead of Person being an abstract class I want it to be an Interface:
#JsonSubTypes(#Type(value=PersonImpl.class, name="PersonImpl"))
#JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="#class")
public interface Person{
public String getName();
public void setName(String name);
}
For some reason this doesn't seem to work, as soon as I do that I start getting Errors when the JsonEncoderDecoder is generated. Has someone been able to achieve this?
Thanks!
Why not define your interface and make your abstract class implement it?
I am using Autobean framework to encode/decode JSON in my GWT application. It works in cases with the interfaces having getters and setters. But is there any way to do it some other way to do this without specifying a setThisCollectionProperty instead using an addToThisCollectionProperty method?
For example, I have an interface IPerson like this:
public interface IPerson {
public String getName();
public void setName(String name);
public int getAge();
public void setAge(int age);
public List<String> getIds();
public void addId(String id);
}
BeanFactory is like this:
public interface BeanFactory extends AutoBeanFactory {
public AutoBean<IPerson> person();
public AutoBean<IPerson> person(IPerson person);
}
and in Person class which implements IPerson,
public class Person implements IPerson {
private String name;
private List<String> ids;
...
public List<String> getIds() {
return ids;
}
public void addId(String id) {
...
ids.add(id);
}
}
It works if the addId(String id) is replaced with setIds(List<String> ids).
Otherwise the following error is shown:
The com.mycompany.jsonsample.beans.IPerson parameterization is not simple, but the person method does not provide a delegate
Is it possible to encode/decode without a set method?
AutoBean manages all getters and setters, and only getters and setters. For any other method, you have to use a category.
Using a category, you could thus implement addId(…) as getIds().add(…), or possibly directly call addIds on the underlying object if the AutoBean is a wrapper.
I used the RestyGWT's JsonEncoderDecoder interface to encode/decode some objects. Among them there are instances of classes having properties not exposed using getter/setter methods. I tried annotating corresponding properties with org.codehaus.jackson.annotate.JsonProperty. But it's not working, causing error
[ERROR] [jsonsample] - field must not be private: com.mycompany.jsonsample.ItemList.items
com.mycompany.jsonsample.ItemList is the class with property items which has no getter/setter and annotated as said above.
Also is it possible to tell the encoder/decoder to skip some properties?
Example with private field and annotated constructor, you should provide more info on your problem though.
public abstract class Parent
{
#JsonCreator
public Parent(#JsonProperty("name") String name)
{
this.name = name;
}
#Override
public String getName()
{
return name;
}
private String name;
}