Below is my code,
Where I am not able to annotate a class with #XmlTransient annotation,
netbeans IDE says annotation type not applicable to this kind of declaration.
I have JDK 1.6 and Jaxb 1.5 running with netbeans.
Thanks for any help.
import com.duncansolutions.databus.external.util.xml.XMLDateAdapter;
import com.duncansolutions.databus.external.xml.parkmobile.PayByCell;
import java.io.Serializable;
import java.util.Date;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlTransient
public class AddTime extends PayByCell implements Serializable{
private Integer transmissionId;
private Integer spaceNumber;
#XmlElement(name = "TransmissionID")
public Integer getTransmissionId() {
return transmissionId;
}
public void setTransmissionId(Integer transmissionId) {
this.transmissionId = transmissionId;
}
#XmlElement(name = "SpaceNumber")
public Integer getSpaceNumber() {
return spaceNumber;
}
public void setSpaceNumber(Integer spaceNumber)
{
this.spaceNumber = spaceNumber;
}
#XmlJavaTypeAdapter(XMLDateAdapter.class)
#XmlElement(name = "StartDateTime")
#Override
public Date getStartTime() {
return startTime;
}
#XmlJavaTypeAdapter(XMLDateAdapter.class)
#XmlElement(name = "EndDateTime")
#Override
public Date getExpTime() {
return expTime;
}
}
#Retention(value=RUNTIME)
#Target(value={FIELD,METHOD})
public #interface XmlTransient
As you can see annotation #XmlTransient only can be applied in FIELDs or METHODS. It is what the API said.
This annotation avoid that a specific member variable will be written in the representation of the object in XML.
http://docs.oracle.com/javaee/5/api/javax/xml/bind/annotation/XmlTransient.html
According to the documentation, #XmlTransient is only applicable to a field or a method, not a class. This is, of course, from Java EE 5; it seems that in Java EE 6 and newer, you're allowed to do so.
If you want to use it, be sure that you're using a newer Java EE JAR.
Related
I have a class with #XmlAccessorType(XmlAccessType.FIELD) annotation, and each private and protected field is annotated with #XmlElement(name='...').
The challenge: I may want to rename one of the xml element names in a later stage. This leads me to the question. Is there a way to override/redefine these annotations, if I create a sub-class ?
I believe that some implementations of JaxB allow for XML configuration to override the annotations. In this case this may actually be possible. Here is an article from Eclipslink explaining how this can be done http://www.eclipse.org/eclipselink/documentation/2.4/solutions/jpatoxml004.htm
In my opinion you can just build an XML configuration for the JaxB file you want to override.
I tried first with the #XmlAccessorType(XmlAccessType.FIELD) and to hide with #XmlTransient. This only works, if you mark the field in the superclass and in the child class with #XmlTransient. But I assume, this is not what you want.
As second approach I've tried with more restrictive #XmlAccessorType(XmlAccessType.PROPERTY) in the superclass and #XmlAccessorType(XmlAccessType.NONE) in the child class. See here my example:
package com.so.example;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/myresource")
public class MyResource {
#GET
#Path("/car")
#Produces(MediaType.APPLICATION_XML)
public Car getCar() {
Car car = new Car();
car.setWheels(4);
return car;
}
#GET
#Path("/suv")
#Produces(MediaType.APPLICATION_XML)
public Suv getSuv() {
Suv suv = new Suv();
List<String> bigWheels = new ArrayList<>();
bigWheels.add("left front wheel");
bigWheels.add("right front wheel");
bigWheels.add("left rear wheel");
bigWheels.add("right rear wheel");
suv.setBigWheels(bigWheels);
return suv;
}
}
Class Car:
package com.so.example;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlAccessorType(XmlAccessType.PROPERTY)
#XmlRootElement
public class Car {
protected Integer wheels;
public Car() {
}
#XmlElement(name = "wheels", nillable = true)
public Integer getWheels() {
return wheels;
}
public void setWheels(Integer wheels) {
this.wheels = wheels;
}
}
Class Suv (Child):
package com.so.example;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#XmlRootElement
#XmlAccessorType(XmlAccessType.NONE)
public class Suv extends Car {
#XmlTransient
private Integer wheels;
private List<String> bigWheels;
public Suv() {
}
#Override
#XmlTransient
public Integer getWheels() {
return wheels;
}
#Override
public void setWheels(Integer wheels) {
this.wheels = wheels;
}
#XmlElement
public List<String> getBigWheels() {
return bigWheels;
}
public void setBigWheels(List<String> bigWheels) {
this.bigWheels = bigWheels;
}
}
One way to "hide" the element wheels of the superclass would be to mark it as "nillable=true" and not use primitive types. In this case, the field wheels will be marshalled to <wheels xsi:nil="true"/>
If it's possible for you to not use the parent class for marshalling and you are only using child classes, you could use the approach described here:
http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html
Also you could use moxy and specify a custom binding:
http://www.eclipse.org/eclipselink/documentation/2.4/moxy/runtime003.htm
Whilst in java, to my knowledge, overriding an annotation #XmlElement(name='...') to change the name property is not possible; you can create a global variable in your code and either pass it through your classes or your functions following the #XmlElement(name='...').
In the code below I created a single class but it contains the setter and getter methods required if you want to pass it through to another class
#XMLAccessorType(XMLAccessType.FIELD)
public class YourClass {
#XmlTransient
private String string = ""; //This can be replaced with whatever variable you are manipulating
//That could be an int or a file or anything really
#XmlElement(name = "your_name")
private void doSomething() {
String temp = getString(); //This variable is normally used to pass between different
//classes but may as well use it if you have one
//Your code which manipulates the String
setString(temp); //This variable is normally used to pass between different classes but
//may as well use it if you have one
}
#XmlElement(name = "your_other_name")
private void doSomethingElse() {
String temp = getString();
//Your code which manipulates the String
setString(temp);
}
public void getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
}
I would reccomend looking at the Java Docs for #XmlTransient and these two other relevant SO questions.
How to override JAXB #XMLAccessorType(XMLAccessType.FIELD) specified at a Class level with #XMLElement on a getter method for a property?
Jaxb - Overriding the XMLElement name attribute
I am using Jackson ObjectMapper to (de)serialize a class with polymorphic nested class. The deserialization of JSON to the class is working fine but when I try to serialize the class to JSON using writeValueAsString function I observe duplicate values in the output
public class Movie {
private String movieName;
#JsonTypeInfo(use=Id.NAME,include=As.EXTERNAL_PROPERTY,property="movieName")
#JsonSubTypes({#JsonSubTypes.Type(value = StarWarsParams.class, name = "starwars")})
private MovieParams movieParams;
/* Getters and setters follow */
}
/* Empty class */
public class MovieParams {
}
public class StarWarsParams extends MovieParams{
private String characterName;
#JsonTypeInfo(use=Id.NAME,include=As.EXTERNAL_PROPERTY,property="characterName")
#JsonSubTypes({#JsonSubTypes.Type(value = SithParameters.class, name = "Darth Vader")})
private CharacterParams characterParams;
/* Getters and setters follow */
}
/* Empty class */
public class CharacterParams {
}
public class SithParameters extends CharacterParams {
private boolean canShootLightning;
}
The code snippet where the conversion is done as follows:
Movie movie = new Movie();
movie.setMovieName("starwars");
StarWarsParams starWarsParams = new StarWarsParams();
starWarsParams.setCharacterName("Darth Vader");
SithParameters sithParameters = new SithParameters();
sithParameters.setCanShootLightning(false);
starWarsParams.setCharacterParams(sithParameters);
movie.setMovieParams(starWarsParams);
ObjectMapper mapper = new ObjectMapper();
String jsonStringSample = mapper.writeValueAsString(movie);
System.out.println(jsonStringSample);
The output, in which movieName and characterName have duplicates are as follows:
{"movieName":"starwars","movieParams":{"characterName":"Darth Vader","characterParams":{"canShootLightning":false},"characterName":"Darth Vader"},"movieName":"starwars"}
This problem appears with older versions of Jackson e.g. 1.9.2 but not the latest ones from com.fasterxml. Jackson identifies 2 fields one from the #JsonTypeInfo annotation and one from the getter. Two solutions :
Use a more recent version of Jackson from com.fasterxml
Move the #JsonTypeInfo annotation over the getter instead of over the field e.g.
#JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY, property = "characterName")
public String getCharacterName() {
return characterName;
}
Customized JSON Object using Serialization is Very Simple.
I have wrote a class in my project to get Serialized JSONObject. i am giving u a Idea to how to Implement this in Project.
Application (POJO Class)
import java.io.Serializable;
import java.util.List;
import org.webservice.business.serializer.ApplicationSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
#JsonSerialize(using=ApplicationSerializer.class)
public class Application implements Serializable {
private static final long serialVersionUID = 1L;
private double amount;
private String businessType;
private String currency;
private int duration;
}
Now ApplicationSerializer class that contains the Customization using Serialization Logic................
package org.webservice.business.serializer;
import java.io.IOException;
import org.webservice.business.dto.Application;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class ApplicationSerializer extends JsonSerializer<Application> {
#Override
public void serialize(Application prm_objObjectToSerialize, JsonGenerator prm_objJsonGenerator, SerializerProvider prm_objSerializerProvider) throws IOException, JsonProcessingException {
if (null == prm_objObjectToSerialize) {
} else {
try {
prm_objJsonGenerator.writeStartObject();
prm_objJsonGenerator.writeNumberField("amount", prm_objObjectToSerialize.getAmount());
prm_objJsonGenerator.writeNumberField("duration", prm_objObjectToSerialize.getDuration());
prm_objJsonGenerator.writeStringField("businesstype", prm_objObjectToSerialize.getBusinessType());
prm_objJsonGenerator.writeStringField("currency", prm_objObjectToSerialize.getCurrency());
} catch (Exception v_exException) {
v_exException.printStackTrace()
} finally {
prm_objJsonGenerator.writeEndObject();
}
}
}
I have a base class declared something like:
package com.mystuff.surrogates;
import java.io.Serializable;
import java.util.UUID;
public class BaseClass implements Serializable {
private UUID id;
private String name;
public UUID getId() { return this.id; }
public void setId(UUID id) { this.id = id; }
public String getName() { return thisname; }
public void setName(String name) { this.name = name; }
}
And a derived class which looks something like:
package com.mystuff.surrogates;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class DerivedClass extends BaseClass {
private String email;
public String getEmail() { return this.email; }
public void setEmail(String email) { this.email = email; }
}
Finally I have a class which I am trying to return as an object from a RESTful webservice call which includes a collection of BaseClass derived class instances and looks rather like:
package com.mystuff.surrogates;
import java.util.ArrayList;
import java.util.List;
public class Response {
List<BaseClass> objectList;
public List<BaseClass> getObjectList() { return this.objectList; }
public void setObjectList(List<BaseClass> objectList) { this.objectList = objectList; }
public void addObject(BaseClass obj) {
if (this.objectList == null) {
this.objectList = new ArrayList<>();
}
this.objectList.add(obj);
}
}
When marshaling this into either XML or JSON, only the members in the base class are included. How do I get Jersey / MOXy to marshal the entire class instance rather than just the base class members? While I have only shown here one derived class, I have several others I would like to potentially chose from to return in the list, so simply using List<DerivedClass> isn't an option since it would preclude returning any of those other classes in the list.
Other information:
Netbeans 8.0.2
Glassfish 4.1 (locally hosted)
Oracle JDK 8U31 (64 bit Windows)
Java EE 7
You'll need to use #XmlSeeAlso so the other classes are binded.
#XmlSeeAlso({DerivedClass.class})
public class BaseClass {
This may not get you the exact desired result, as the marshalled data will have a reference to the type. For instance with XML, you will see
<objectList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="derivedClass">
and JSON you will see
{"objectList":[{"type":"derivedClass",...
You can have a look at this answer for an idea of how to get rid of the type property if it's undesired.
As far as the JSON is concerned, using Jackson will not have this behavior. You can simply use jersey-media-json-jackson, which Glassfish also comes shipped with (you can add it as a dependency in a provided scope), and just register the JacksonFeature with the application.
I am using the Play Framework in it's current version and my model classes extend play.db.jpa.JPABase.
Today I tried to make an often used type of query generic and define a static helper method to construct it.
I wrote the following:
import play.db.jpa.Model;
import play.libs.F;
public class GenericQueries {
public static <T extends Model> F.Option<T> firstOption(
Class<T> clazz,
String query,
Object... parameters){
final T queryResult = T.find(query,parameters).first();
return (queryResult == null) ?
F.Option.<T>None() :
F.Option.Some(queryResult);
}
}
However, I get the following error:
Execution exception
UnsupportedOperationException occured : Please annotate your JPA model with #javax.persistence.Entity annotation.
I debugged into the method, at runtime T seems to be correctly set to it's corresponding Model class. I even see the annotation.
I suspect some class enhancing voodoo by the play guys responsible for this, but I am not entirely sure.
Any ideas?
Update: added Model class as Requested
Here is a shortened Version of one of the Model classes I use.
package models;
import org.apache.commons.lang.builder.ToStringBuilder;
import play.data.validation.Required;
import play.db.jpa.Model;
import play.modules.search.Field;
import play.modules.search.Indexed;
import javax.persistence.Column;
import javax.persistence.Entity;
import java.util.Date;
#Entity #Indexed
public class FooUser extends Model {
#Required
public Date firstLogin;
#Field
#Required(message = "needs a username")
#Column(unique = false,updatable = true)
public String name;
#Field
public String description;
#Required
public boolean isAdmin;
#Override
public String toString(){
return new ToStringBuilder(this)
.append("name", name)
.append("admin", isAdmin)
.toString();
}
}
In Play entites should extend play.db.jpa.Model and use #Entity annotation (class level).
For what you say I understand that you are extending play.db.jpa.JPABase.
This may be the reason of the issue, as Play (as you point) dynamically enhances classes and it may be clashing with your inheritance.
EDIT: I tested the issue
The problem is that Play is not enhancing the object T. This means that the find method called id the one of GenericModel (parent of Model) whose implementation is to throw an exception with the message.
The enhancer seems to detect only the classes with #Entity.
Even the solution of mericano1 doesn't work, the enhancer doesn't pick it. So I feel you won't be able to use that method in Play.
The best way to do that is to use a base class that extends play.db.jpa.Model with just the static methods that will be shared by the subclasses.
Add the #Entity annotation to the base class and no class fields.
import play.db.jpa.Model;
import play.libs.F;
public class BaseModel extends Model {
public static <T extends Model> F.Option<T> firstOption(
Class<T> clazz,
String query,
Object... parameters){
final T queryResult = T.find(query,parameters).first();
return (queryResult == null) ?
F.Option.<T>None() :
F.Option.Some(queryResult);
}
}
And then
#Entity
public class FooUser extends BaseModel {
....
}
I'm having an issue generating XML via Java code. I have a class that for SailingAvailabilityResponseMessage. Within this class there are several other classes that are also used in the method I'm writing. Here is a snippet of what the SailingAvailabilityResponseMessage classes looks like:
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
#XmlType(propOrder={"type", "agency", "version", "release", "processingInfo", "advisoryMessage", "packageDescription", "sailingGroup", "registrationInformation"})
public class SailingAvailabilityResponseMessage {
private ProcessingInfo processingInfo;
private AdvisoryMessage advisoryMessage;
private PackageDescription packageDescription;
private SailingGroupResponse[] sailingGroup;
private RegistrationInformation registrationInformation;
String type;
#XmlAttribute
public String getType() {
return type;
}
The specific issue I'm encountering is related to the SailingGroupResponse[] sailingGroup;
SailingGroupResponse[] inherits from sailingGroup. Here is what sailingGroup looks like:
public class SailingGroup {
private SailingDescription sailingDescription;
public SailingDescription getSailingDescription() {
return sailingDescription;
}
public void setSailingDescription(SailingDescription sailingDescription) {
this.sailingDescription = sailingDescription;
}
And here is what SailingGroupResponse[] looks like:
import javax.xml.bind.annotation.XmlType;
#XmlType(propOrder={"sailingInformation", "diningDetails", "modeOfTransportation", "currencyInfo", "packageDescription"})
public class SailingGroupResponse extends SailingGroup {
private SailingInformation sailingInformation;
private DiningDetails diningDetails;
private ModeOfTransportation modeOfTransportation;
private CurrencyInfo currencyInfo;
private PackageDescription packageDescription;
The problem I'm encountering with the XML generation is that I'm expecting a tag of <sailingGroup> which I get but then I also get a tag of <sailingGroupResponse> which I do not want as it is not part of the original specs I'm following. I'm generating the XML via WebSphere RDi. I'm on SOAP 1.2 but the business partner I'm trying to develop for is on SOAP 1.1 so instead of being able to use JAX-WS runtime, I'm having to use JAX-RPC (apache AXIS will not allow me to generate).
Is anyone familiar with JAX-RPC runtime and issues similar to the one I'm asking? If anyone knows of a good site for me to visit for additional information, I'm willing to research further although so far I've not had much success in finding an answer.
Thanks,
Caren
Introducing polymorphism into JAXB-annotated classes usually causes complications, as you're finding out.
Try this:
#XmlElement(type = SailingGroup.class)
public SailingGroupResponse[] getSailingGroup() {
return sailingGroup;
}
And you may also need to add #XmlType to SailingGroup.
Are you sure that JAXB is producing the sailingGroupResponse tag? When I run the following stripped down example I get reasonable XML:
XML Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<sailingGroup/>
<sailingGroup/>
</root>
Demo Code
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;
public class Demo {
public static void main(String[] args) throws Exception {
SailingAvailabilityResponseMessage sarm = new SailingAvailabilityResponseMessage();
SailingGroupResponse[] sgr = new SailingGroupResponse[2];
sgr[0] = new SailingGroupResponse();
sgr[1] = new SailingGroupResponse();
sarm.setSailingGroup(sgr);
JAXBElement<SailingAvailabilityResponseMessage> rootElement = new JAXBElement<SailingAvailabilityResponseMessage>(new QName("root"), SailingAvailabilityResponseMessage.class, sarm);
JAXBContext jc = JAXBContext.newInstance(SailingAvailabilityResponseMessage.class, SailingGroup.class, SailingGroupResponse.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(rootElement, System.out);
}
}
SailingAvailabilityResponseMessage
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
#XmlType(propOrder = { "type", "sailingGroup"})
public class SailingAvailabilityResponseMessage {
private SailingGroupResponse[] sailingGroup;
String type;
public SailingGroupResponse[] getSailingGroup() {
return sailingGroup;
}
public void setSailingGroup(SailingGroupResponse[] sailingGroup) {
this.sailingGroup = sailingGroup;
}
#XmlAttribute
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
SalingGroupResponse
public class SailingGroupResponse extends SailingGroup {
}
SailingGroup
public class SailingGroup {
}