I am trying to annotate my java method as #XmlTransient in my java class like below.
#XmlAccessorType(XmlAccessType.PROPERTY)
public abstract class MyClass {
#XmlTransient
public void addsomething{
// do something
}
}
When I try to use this class in my JaxBContext through other class I am getting following exception
JAXB annotation is placed on a method that is not a JAXB property
this problem is related to the following location:
at #javax.xml.bind.annotation.XmlTransient()
,
But when I see XmlTransient() annotation definition(#Target(value={FIELD,METHOD,TYPE})) it's clearly said be to work with methods. And In the JavaDoc(http://docs.oracle.com/javaee/7/api/javax/xml/bind/annotation/XmlTransient.html) it says
The #XmlTransient annotation can be used with the following program elements:
a JavaBean property
field
class
Can't I use #XmlTransient on methods?
The only methods that #XmlTransient can be used are those that begin with get or set. These methods used in combination are used to expose a property in Java. #XmlTransient can be placed on either the get or set method.
Get Method
The get method must take no parameters and return a value:
public String getFoo() {
return foo;
}
Set Method
The set method must take one parameter.
public void setFoo(String foo) {
this.foo = foo;
}
Related
The following results in a MappingException. Do I need to change my design?
public class Foo extends Bar {
// if class == Foo do not send this over the wire
#JsonProperty(access = Access.WRITE_ONLY)
public List<X> myList;
}
public class Bar {
// if class == Bar send this over the wire
public List<X> myList;
public void methodsThatAccessMyList() {
// multiple methods exists in here accessing myList
// also, other classes exist extending bar,
//so moving these to the children will result in duplicate code
}
}
However, I need the json property on the child class, to prevent the child class to transport that field over the wire.
What do I need to change to prevent the ambiguous mapping?
org.springframework.data.mapping.MappingException: Ambiguous field
mapping detected! Both protected java.util.List ... and
#com.fasterxml.jackson.annotation.JsonProperty(index=-1,
access=WRITE_ONLY, value="", defaultValue="", required=false)protected
java.util.List ... map to the same field name ...! Disambiguate using
#Field annotation!
It turns out you can put the JsonProperty on the getter of the field, it will work as expected.
Like this, you don't need to override the field itself in the extending class.
I have an object named AddOnsSRO.Only on serialization I want the names of fields of the object to be changed.
Tried using #JsonProperty on getter methods but it gives me a renamed field even on usages where serialization is not involved.
public class AddOnsSRO {
private String sideCar;
private String sideCarCoverage;
#JsonSerialize
#JsonProperty("abc")
public String getSideCar() {
return sideCar;
}
public void setSideCar(String sideCar) {
this.sideCar = sideCar;
}
#JsonSerialize
#JsonProperty("xyz")
public String getSideCarCoverage() {
return sideCarCoverage;
}
public void setSideCarCoverage(String sideCarCoverage) {
this.sideCarCoverage = sideCarCoverage;
}
}
Only on serialization the following fields : sideCar and sideCarCoverage must be renamed to abc and xyz respectively.
For any other use except serialization the field names should be sideCar and sideCarCoverage only.
Please help and suggest changes or annotations accordingly.
For effecting only serializing use #JsonGetter instead of #JsonProperty
#JsonGetter("abc")
public String getSideCar() {
return sideCar;
}
Getter means that when serializing Object instance of class that has this method (possibly inherited from a super class), a call is made through the method, and return value will be serialized as value of the property.
You can add #JsonSetter to setter method for deserialize:
#JsonSetter("sideCar")
public void setSideCar(String sideCar) {
this.sideCar = sideCar;
}
your code looks good...Please upgrade your jackson lib... if you are using old
I am using Lombok library in my project and I am not able to use a class annotated with #Builder in outer packages.
Is there a way to make the builder public?
MyClass instance = new MyClass.MyClassBuilder().build();
The error is:
'MyClassBuilder()' is not public in
'com.foo.MyClass.MyClassBuilder'. Cannot be accessed
from outside package
#Builder already produces public methods, it's just the constructor that's package-private. The reason is that they intend for you to use the static builder() method, which is public, instead of using the constructor directly:
Foo foo = Foo.builder()
.property("hello, world")
.build();
If you really, really, really want the constructor to be public (there seems to be some suggestion that other reflection-based libraries might require it), then Lombok will never override anything that you've already declared explicitly, so you can declare a skeleton like this with a public constructor and Lombok will fill in the rest, without changing the constructor to package-private or anything.
#Builder
public class Foo
{
private final String property;
public static class FooBuilder
{
public FooBuilder() { }
// Lombok will fill in the fields and methods
}
}
This general strategy of allowing partial implementations to override default behaviour applies to most (maybe all) other Lombok annotations too. If your class is annotated with #ToString but you already declared a toString method, it will leave yours alone.
Just to show you everything that gets generated, I wrote the following class:
#Builder
public class Foo
{
private final String property;
}
I then ran it through delombok to see everything that was generated. As you can see, everything is public:
public class Foo
{
private final String property;
#java.beans.ConstructorProperties({"property"})
Foo(final String property) {
this.property = property;
}
public static FooBuilder builder() {
return new FooBuilder();
}
public static class FooBuilder
{
private String property;
FooBuilder() { }
public FooBuilder property(final String property) {
this.property = property;
return this;
}
public Foo build() {
return new Foo(property);
}
public String toString() {
return "Foo.FooBuilder(property=" + this.property + ")";
}
}
}
The problem is you are using #Builder in the wrong way.
When Builder Pattern is used, you only need to use the static method to invoke it and then build, for example:
MyClass instance = MyClass.builder().build(); .
Please do not new the MyClassBuilder again, it breaks the encapsulation the pattern has since you are directly using the inner MyClassBuilder class. This constructor is been hided from outside, that's why you get the not accessible error. Instead it provides you the static method builder().
I have found this neat workaround:
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
#Getter
#Setter
#Builder
public class Customer {
private String id;
private String name;
public static MessageBuilder builder() {return new CustomerBuilder();}
}
The problem with this builder annotation is that, if you delombok you'll see, the generated constructor for the builder has no access indicator (public, private, protected) therefore is only visible within the same package.
This would work if the extended classes were in the same package.
I'm having the same problem and I think that lombok does not support this, for now.
I was able to find the feature request in here https://github.com/rzwitserloot/lombok/issues/1489
My suggestion is to hard implement builder pattern in this class.
as mentioned you can use the builder, now instead of user property builder() will return the instance create so you can treat as normal builder ( no need to use property)
instance = MyClass.MyClassBuilder().property1(value1).property1(value2).build();
Imagine an annotation called "MyAnn" with runtime retention, a class MyClass, and an abstract class called MyData. MyClass has a field of type MyData, annotated with MyAnn. Within the instance of MyData, how do see if the annotation MyAnn is present and retrieve its information?
Note - in Java8 I know we can directly annotate the inner class at construction - and that works - but I need this working based on the field annotation.
Thanks for any help!
public MyClass extends MySuperClass() {
#MyAnn(value = "something")
protected MyData mydata;
public void doSomething() {
mydata = new MyData() {};
mydata.initialize();
}
}
public abstract MyData() {
String myValue = null;
public void initialize() {
if (***I am annotated with MyAnn) {
myValue = (***value from annotation MyAnn);
}
}
}
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnn {
String myvalue;
}
MyData cannot directly know whether it has been annotated with MyAnn, because it has no knowledge of whether the current instance is a field or a standalone instance, and if it is a field, then whether the field has or has not been annotated with MyAnn.
So, you will need to somehow obtain and pass the value to initialize(), and you will need to somehow obtain the value at the place where initialize() is called. And from your code, it appears that "something" can be passed as a parameter to initialize(), making the whole thing a lot easier than annotating the field and then checking whether the field is annotated.
But in any case, if you want to check whether a field is annotated, you have to:
obtain the fields of your class with getClass().getDeclaredFields()
loop over the fields; for each field, either
invoke isAnnotationPresent( MyAnn.class ) or
invoke field.getAnnotations(), loop for each annotation, and check whether this annotation instanceof MyAnn.class
Once you have found the annotation, you can get its value with annotation.value();
I have a class
#Entity
public class MyClass extends BaseClass {
...
public boolean isOpenAt(Date x) {
return true; // or whatever
}
}
#MappedSuperclass
#Access(AccessType.Field)
public abstract class BaseClass {
...
}
Running mvn datanucleus:enhance I get the error org.datanucleus.metadata.InvalidClassMetaDataException: "MyClass.openAt" : declared in MetaData, but this field doesnt exist in the class! Any idea why?
I'm using org.datanucleus:datanucleus-core:3.2.7, org.datanucleus:datanucleus-accessplatform-jpa-rdbms:3.3.2, org.eclipse.persistence:javax.persistence:2.1.0, org.datanucleus:datanucleus-maven-plugin:3.3.0-release.
Disclaimer: I have no idea what datanucleus is.
That said, it's likely that isOpenAt() method gets treated as a getter (similar to getFirstName(), say), since according to According to the JavaBeans spec,
Boolean properties
In addition, for boolean properties, we allow a
getter method to match the pattern:
public boolean is<PropertyName>();
This "isPropertyName" method may be provided instead of a
"get" method, or it may be provided in addition to a
"get" method. In either case, if the is
method is present for a boolean property then we will use the
"is" method to read the property value. An example
boolean property might be:
public boolean isMarsupial(); public void setMarsupial(boolean m);
Try renaming isOpenAt() into seeIfOpenAt() and see if that helps.