JAXB null instead empty string during marshaling - java

How I can print 'null' as field value, when marshalling the string?
Example: error and error_code are Strings, and i want to use 'null' as a value indicating that there is no value/errors happened on the server side.
{
"error_code": null,
"error": null
}
Today, I have to use EMPTY values, so that "error_code" or "error" these fields generally fall into json, and if they were not explicitly initialized as this.errorCode = StringUtils.EMPTY;
So today, I have next json:
{
"error_code": "",
"error": ""
}
This is how that looks in a code:
#XmlRootElement()
#XmlAccessorType(XmlAccessType.FIELD)
public class Response
{
#SuppressWarnings("unused")
private static final Logger log = LoggerFactory.getLogger(Response.class);
public static final String ERROR_FIELD_NAME = "error";
public static final String ERROR_CODE_FIELD_NAME = "error_code";
// #XmlJavaTypeAdapter(CafsResponse.EmptyStringAdapter.class)
#XmlElement(name = Response.ERROR_CODE_FIELD_NAME)
private String errorCode;
// #XmlJavaTypeAdapter(CafsResponse.EmptyStringAdapter.class)
#XmlElement(name = Response.ERROR_FIELD_NAME)
private String errorMessage;
// Empty Constructor
public Response()
{
this.errorCode = StringUtils.EMPTY; // explicit initialization, otherwise error_code will not appear as part of json, how to fix this this ?
this.errorMessage = StringUtils.EMPTY;
}
etc...
// Empty Constructor
public Response()
{
this.errorCode = null; // this variant dosn't work either, and error_code again didn't get to json
this.errorMessage = null;
}
See, #XmlJavaTypeAdapter, i thought that this potentially could help me - but no :)
Instead of null value, i'm getting "null" as string.
if (StringUtils.isEmpty(str))
{
return null;
}
return str;
{
"error_code": "null", // this is not whta i wanted to get.
"error": "null"
}
Any help on this? - ask me if something is not clear.
full list:
/**
* Empty string Adapter specifying how we want to represent empty strings
* (if string is empty - treat it as null during marhsaling)
*
*/
#SuppressWarnings("unused")
private static class EmptyStringAdapter extends XmlAdapter<String, String>
{
#Override
public String unmarshal(String str) throws Exception
{
return str;
}
#Override
public String marshal(String str) throws Exception
{
if (StringUtils.isEmpty(str))
{
return null;
}
return str;
}
}

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
You could use MOXy as your JSON provider to support this use case. Below is an example:
Response
MOXy will marshal properties marked with #XmlElement(nillable=true) to the representation you are looking for
(see: http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html).
package forum11319741;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Response {
public static final String ERROR_FIELD_NAME = "error";
public static final String ERROR_CODE_FIELD_NAME = "error_code";
#XmlElement(name = Response.ERROR_CODE_FIELD_NAME, nillable = true)
private String errorCode;
#XmlElement(name = Response.ERROR_FIELD_NAME, nillable = true)
private String errorMessage;
}
jaxb.properties
To use MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
package forum11319741;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Response.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty("eclipselink.media-type", "application/json");
marshaller.setProperty("eclipselink.json.include-root", false);
Response response = new Response();
marshaller.marshal(response, System.out);
}
}
Output
{
"error_code" : null,
"error" : null
}
MOXy and JAX-RS
You can use the MOXyJsonProvider class to enable MOXy as your JSON provider in your JAX-RS application (see: http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html).
package org.example;
import java.util.*;
import javax.ws.rs.core.Application;
import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
public class CustomerApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>(2);
set.add(MOXyJsonProvider.class);
set.add(CustomerService.class);
return set;
}
}
For More Information
http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html

Related

Java : Not getting namespace in generated XML

I have to build an XML file from a java object in a java maven project.
I have a class named CrossIndustryInvoice with XML annotations.
#Data
#Builder
#AllArgsConstructor #NoArgsConstructor
#XmlRootElement(name="CrossIndustryInvoice", namespace = NamespaceMapper.RSM_URI)
#XmlAccessorType(XmlAccessType.FIELD)
public
class CrossIndustryInvoice {
#XmlElement(name = "ExchangedDocumentContext", namespace = NamespaceMapper.RSM_URI)
private ExchangedDocumentContext exchangedDocumentContext;
#XmlElement(name = "ExchangedDocument", namespace = NamespaceMapper.RSM_URI)
private ExchangedDocument exchangedDocument;
#XmlElement(name = "SupplyChainTradeTransaction", namespace = NamespaceMapper.RSM_URI)
private SupplyChainTradeTransaction supplyChainTradeTransaction;
}
I also created a class named NamespaceMapper where i define the different namespaces used in my XML
public class NamespaceMapper extends NamespacePrefixMapper {
public static final String QDT_PREFIX = "qdt"; // DEFAULT NAMESPACE
public static final String QDT_URI = "urn:un:unece:uncefact:data:standard:QualifiedDataType:100";
public static final String RAM_PREFIX = "ram"; // DEFAULT NAMESPACE
public static final String RAM_URI = "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100";
public static final String RSM_PREFIX = "rsm"; // DEFAULT NAMESPACE
public static final String RSM_URI = "urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100";
public static final String UDT_PREFIX = "udt"; // DEFAULT NAMESPACE
public static final String UDT_URI = "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100";
public static final String XSI_PREFIX = "xsi"; // DEFAULT NAMESPACE
public static final String XSI_URI = "http://www.w3.org/2001/XMLSchema-instance";
#Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
if(QDT_PREFIX.equals(namespaceUri)) {
return QDT_PREFIX;
}
if(RAM_PREFIX.equals(namespaceUri)) {
return RAM_PREFIX;
}
if(RSM_PREFIX.equals(namespaceUri)) {
return RSM_PREFIX;
}
if(UDT_PREFIX.equals(namespaceUri)) {
return UDT_PREFIX;
}
if(XSI_PREFIX.equals(namespaceUri)) {
return XSI_PREFIX;
}
return suggestion;
}
#Override
public String[] getPreDeclaredNamespaceUris() {
return new String[] { QDT_URI, RAM_URI, RSM_URI, UDT_URI, XSI_URI };
}
}
I also created a package-info.java file
#XmlSchema(
elementFormDefault= XmlNsForm.QUALIFIED,
namespace="http://www.example.com/FOO",
xmlns={
#XmlNs(
prefix="ns1",
namespaceURI="http://www.example.com/FOO"),
#XmlNs(
prefix="qdt",
namespaceURI="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"),
#XmlNs(
prefix="ram",
namespaceURI="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"),
#XmlNs(
prefix="rsm",
namespaceURI="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"),
#XmlNs(
prefix="udt",
namespaceURI="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"),
#XmlNs(
prefix="xsi",
namespaceURI="http://www.w3.org/2001/XMLSchema-instance"),
}
)
package fr.dsidiff.app.ui.model.request.metadata;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
In my application, I do have a method that converts Java Object to XML String.
private String payloadToXml(CrossIndustryInvoice invoice) throws JAXBException {
//Create JAXB Context
JAXBContext ctx = null;
try {
ctx = JAXBContext.newInstance(CrossIndustryInvoice.class);
Marshaller jaxbMarshaller = ctx.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter sw = new StringWriter();
jaxbMarshaller.marshal(invoice, sw);
return sw.toString();
} catch (JAXBException e) {
e.printStackTrace();
throw new JAXBException("Oops something went wrong");
}
}
My problem is that the XML i generate is invalid and namespaces are not matching.
here is a sample of XML I obtain :
<ns2:CrossIndustryInvoice xmlns="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:ns2="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:ns4="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" xmlns:ns3="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
<ns2:ExchangedDocumentContext>
<BusinessProcessSpecifiedDocumentContextParameter>
<ID>A1</ID>
</BusinessProcessSpecifiedDocumentContextParameter>
<GuidelineSpecifiedDocumentContextParameter>
<ID>urn:factur-x.eu:1p0:basicwl</ID>
</GuidelineSpecifiedDocumentContextParameter>
</ns2:ExchangedDocumentContext>
While i should get something different:
<?xml version='1.0' encoding='UTF-8'?>
<rsm:CrossIndustryInvoice xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<rsm:ExchangedDocumentContext>
<ram:BusinessProcessSpecifiedDocumentContextParameter>
<ram:ID>A1</ram:ID>
</ram:BusinessProcessSpecifiedDocumentContextParameter>
<ram:GuidelineSpecifiedDocumentContextParameter>
<ram:ID>urn:factur-x.eu:1p0:basicwl</ram:ID>
</ram:GuidelineSpecifiedDocumentContextParameter>
</rsm:ExchangedDocumentContext>
I didn't pay attention to the import. In my pom.xml I added the following dependency:
<!-- https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.0.1</version>
</dependency>
In my NamespaceMapper class I was using the following import
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
I replaced it with :
import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;

Modify POJO class fields with custom setter or custom annotation (in Spring Boot)

Given a POJO in Spring Boot with several dozen fields of type String which is deserialized by Jackson. For demonstration purposes the following example only contains three fields:
#NoArgsConstructor
public class SomeRequest {
#JsonProperty("field_1")
private String field1;
#JsonProperty("field_2")
private String field2;
#JsonProperty("field_3")
private String field3;
}
I'm looking for a way to override the setter method but only for certain fields, i.e. I'd like to avoid repeating the below code for every affected field. This is doable for a handful number of fields but gets tedious for more than a handful.
public setField2(String field2) {
this.field2 = field2 + "?";
}
My idea was to place an annotation on the field like this:
#NoArgsConstructor
public class SomeRequest {
// ...
#JsonProperty("field_2")
#AppendQuestionMark
private String field2;
// ...
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface AppendQuestionMark {
}
But I'm lacking information on how to "implement" the AppendQuestionMark annotation which would override the field's setter method.
Or am I thinking way too complicated?
You can't change the settermethod's body if that's what you are asking. But you can create a method that will take an object (i.e. SomeRequest) as input and check which fields have your Annotation and change the values for those fields as you want.
For example, I created an annotation AppendStr.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface AppendStr {
public String str();;
}
Then I created another class 'AppendStrImpl` that will handle the implementation. I used the following code -
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class AppendStrImpl {
public void changeFields(Object object) throws Exception {
Class<?> clazz = object.getClass();
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
if (field.isAnnotationPresent(AppendStr.class)) {
// get the getter method name from the field name
String fieldName = field.getName();
String getterMethodName =
"get" +
fieldName.substring(0, 1).toUpperCase() +
fieldName.substring(1);
Method getterMethod = clazz.getMethod(getterMethodName);
String returnValue = (String) getterMethod.invoke(object);
String setterMethodName = getterMethodName.substring(0, 1).replace("g", "s")
+ getterMethodName.substring(1);
Method setterMethod = clazz.getMethod(setterMethodName, String.class);
setterMethod.invoke(object, returnValue + getAppendingString(field));
System.out.println((String) getterMethod.invoke(object));
}
}
}
private String getAppendingString(Field field) {
return field.getAnnotation(AppendStr.class)
.str();
}
}
And this is my POJO class -
public class POJO {
#AppendStr(str = "?")
private String filed1;
#AppendStr(str = "!")
private String filed2;
private String filed3;
#AppendStr(str = "+")
private String filed4;
// ... getters and setters
}
Then I called this method from the main method -
POJO pojo = new POJO("a", "b", "c", "d");
AppendStrImpl appendStrImpl = new AppendStrImpl();
try {
appendStrImpl.changeFields(pojo);
} catch (Exception e) {
e.printStackTrace();
}
Now you can make this call with hard coding or you can use #Aspect too if you want.
The github link is here.
Instead of creating a new annotation that appends a question mark to one generic string field in your pojo you can use the already present JsonDeserialize annotation over the string fields you are interested:
#Data
#NoArgsConstructor
public class SomeRequest {
#JsonProperty("field_1")
private String field1;
#JsonProperty("field_2")
//here the custom deserializer appends the question mark character
#JsonDeserialize(using = StringAppendQuestionMarkDeserializer.class)
private String field2;
}
In your spring boot project you can register the custom deserializer with the JsonComponent annotation like below:
#JsonComponent
public class StringAppendQuestionMarkDeserializer extends JsonDeserializer<String> {
#Override
public String deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
return node.asText() + "?";
}
}
A spring boot test example using the custom deserializer:
#JsonTest
class CorespringApplicationTests {
#Test
void testDeserialize() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
SomeRequest request = mapper.readValue("{\"field_1\":\"value1\",\"field_2\":\"value2\"}", SomeRequest.class);
System.out.println(request); //<-- SomeRequest(field1=value1, field2=value2?)
}
}
Something like the following should do the trick:
#Aspect
#Component
public class AppendQuestionMarkAspect {
#Around("#annotation(AppendQuestionMark)")
public Object appendQuestionMark(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] arguments = joinPoint.getArgs();
return joinPoint.proceed(new Object[] {((String) arguments[0]) + "?"});
}
}
Of course, it would be advisable to check that only one argument exists and that it is, in fact, a String. Or you can also define the pointcut as to be applied only to methods starting with set. But the essence of the code is there.

How to automatic decode Dto from GET query parameters

I Have a GET request with some parameters which I handle as an object on the controller, consider it could be several parameters.
The problem is that the values for the properties on the dto are being filled using url encoding which I dont want because it messes up queries to a database later on, ie.: name gets populated with "some%20name" instead of "some name" as I would expect.
How can I avoid this encoding problem?
Bellow is a small scenario that represents my issue:
public class SomeDto {
private String name;
private String hex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHex() {
return hex;
}
public void setHex(String hex) {
this.hex = hex;
}
}
#RestController
#RequestMapping("example")
public class RestController {
#GetMapping
public void example(final SomeDto someDto) {
System.out.println(someDto.getName());
System.out.println(someDto.getHex());
}
}
public class ClientApi {
private RestTemplate restTemplate;
private String hostUri;
public ClientApi(RestTemplate restTemplate, String hostUri) {
this.restTemplate = restTemplate;
this.hostUri = hostUri;
}
public void test(SomeDto someDto) {
var uri = UriComponentsBuilder.fromUriString(hostUri + "/example");
if(someDto != null) {
uri.queryParam("name", someDto.getName())
.queryParam("hex", someDto.getHex());
}
restTemplate.exchange(uri.toUriString(), HttpMethod.GET, null, Void.class);
}
}
#SpringBootTest(
classes = DemoApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
class ClientApiTest {
#LocalServerPort
private String port;
private ClientApi clientApi;
#BeforeEach
void before() {
clientApi = new ClientApi(new RestTemplate(), "http://localhost:" + port);
}
#Test
void testMethod() {
SomeDto someDto = new SomeDto();
someDto.setName("some name");
someDto.setHex("#ffffff");
clientApi.test(someDto);
}
}
UPDATE:
I was able to partially fix it by decoding the URL, however it only fixes name "some name" to reach the controller correctly, hex "#ffffff" on the other hand reaches as null.
var decodedUri = URLDecoder.decode(uri.toUriString(), Charset.defaultCharset());
Spring uses some symbols as service symbols.
E.g. you cannot parse param value if it contains a comma.
?someParam=some,value
Would be parsed as two params: some and value. But if receive type is not array or collection then the second value will be ignored. Hence, you'll get someParam=some.
The simplest way to avoid it is URL params base64 encoding.
For me, the convenient way was to encode params as json in Base64.
{
"name": "some name",
"hex": "fffffff"
}
Why json? Because there are many ready-made solutions for parsing JSON into an object.
So, your controller will receive Base64 value which is eyJuYW1lIjoic29tZSBuYW1lIiwgImhleCI6ImZmZmZmZmYifQ==
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.Base64;
import java.util.Objects;
#RestController
public class RestController {
#GetMapping("/example")
public void example(String params) {
String decoded = decodeBase64(params);
SomeDto dto = parseTo(decodedFilters, SomeDto.class);
}
public String decodeBase64(String encoded) {
if (Objects.nonNull(encoded)) {
return new String(Base64.getDecoder().decode(encoded));
}
return "";
}
public <T> T parseTo(String jsonAsString, Class<T> classType) {
String toParse = Objects.nonNull(jsonAsString) ? jsonAsString : "{}";
try {
return new ObjectMapper().readValue(toParse, classType);
} catch (IOException e) {
throw new ValidationException(e.getMessage());
}
}
}

Display XML correctly in Firefox with Jackson

I'm converting a JSON file into an ArrayList and then to XML by using Jackson. It is displayed in Firefox but just as a normal String. By using the inspect element tool I get the whole formatted xml though. Which function can I use to display it correctly on the browser?
My method:
private void init() throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
InputStream is = MyClass[].class.getResourceAsStream("/config/myList.json");
myList= Arrays.asList(mapper.readValue(is, MyClass[].class));
XmlMapper xmlMapper = new XmlMapper();
for(MyClass test : myList){
String asXml += xmlMapper.writeValueAsString(test);
}
LOGGER.info("asXml: {}.", asXml);
}
Desired output in browser:
<myclass xmlns="">
<myclass>XyClass</ci>
<myname>XyName</ci>
...
</myclass>
Actual output:
XyClassXyName...
Quite simplified the class looks like this:
#JacksonXmlRootElement(localName ="MyClass")
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
#JsonInclude(JsonInclude.Include.NON_NULL)
public class MyClass {
#XmlElement(required = true)
private String class;
#XmlElement(required = true)
private String name;
//....
//standard constructor
public MyClass() { }
public CI(String class, String name){
this.class = class;
this.name = name;
}
public String getClass() {
return class;
}
public String getName() {
return name;
}
public void setClass(String class) {
this.class = class;
}
public void setName(String name) {
this.name = name;
}
}
Another weird thing is that I have the exact annotations in another class, trying the same thing with that and there the browser does not display anything... Thanks for any help.
Well my mistake derived from two things basically. Most important is the definiton of the XML Root Element (not only as annotation in your "MyClass"). Define a global String to create a XML Root element, otherwise your document won't be well-formed and the mistake "junk after document element" will be shown.
private String asXml ="<?xml version=\"1.0\" encoding=\"utf-8\"?><MyList>";
I've adapted the method to:
private void init() throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
InputStream is = MyClass[].class.getResourceAsStream("/config/myList.json");
myList= Arrays.asList(mapper.readValue(is, MyClass[].class));
XmlMapper xmlMapper = new XmlMapper();
for(MyClass test : myList){
String asXml += xmlMapper.writer().with(SerializationFeature.WRAP_ROOT_VALUE).withRootName("MyClass").writeValueAsString(test);
}
LOGGER.info("asXml: {}.", asXml);
asXml += "</MyList>";
}
And don't forget to add the correct MediaType in your RestController:
#RequestMapping(value="/display", method=RequestMethod.GET, produces=MediaType.APPLICATION_XML_VALUE)
public #ResponseBody String getList(Model model) {
return service.getAsXmlString();
}

REST xml answer - Jaxb - Amazon product API

I'm currently (trying) to work with the amazon product API to search thourgh items.
I have the response in XML, but i have an exception in jaxb, maybe i missed something..
Here is the XML :
XML response from Amazon
I want to extract items informations, but i'm getting some trouble.
Item class:
#XmlRootElement(name="ItemSearchResponse")
public class AmazonItem
{
private String name;
private String asin;
private String price;
public AmazonItem()
{
}
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlElement(name="Title")
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlElement(name="ASIN")
public String getAsin()
{
return asin;
}
public void setAsin(String asin)
{
this.asin = asin;
}
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlElement(name="FormattedPrice")
public String getPrice()
{
return price;
}
public void setPrice(String price)
{
this.price = price;
}
}
my builder :
public class AmazonItemBuilder
{
public AmazonItemBuilder()
{
}
public List<AmazonItem> build(InputStream response)
{
try
{
JAXBContext context = JAXBContext.newInstance(AmazonItem.class);
Unmarshaller unMarshaller = context.createUnmarshaller();
AmazonItem newItem = (AmazonItem) unMarshaller.unmarshal(response);
System.out.println(newItem);
}
catch (JAXBException e)
{
e.printStackTrace();
}
return null;
}
}
the "response" come from a URL response.openStream();
OK i forgot the error -_-
javax.xml.bind.UnmarshalException:
unexpected element (uri:"http://webservices.amazon.com/AWSECommerceService/2011-08-01", local:"ItemSearchResponse"). Expected elements are <{}ItemSearchResponse>
Thank you !
It appears that the XML document is namespace qualified. You can use the package level #XmlSchema location annotation to specify the namespace qualification for the entire document. Package level annotations go on a special call called package-info that looks like the following:
package-info
#XmlSchema(
namespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01",
elementFormDefault = XmlNsForm.QUALIFIED)
package com.your.pkg;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
I hope the top level class to covert the response to object should be "ItemSearchResponse", try creating a class with member variable "Items" which inturn will have another member object array "AmazonItem"

Categories

Resources