Confused as how to use JAXB XML Adapter for my requirement
Asked Answered
U

3

8

I am Using JAXB for unmarshalling process , for which the request comes from the UI to our service class . The below is the format of XML request .

<SampleRequest  user="testUser"  account="testAccount"    Specifier=  "value1a,value1b,value1c : name2a,value2b,value2c"/>

My requirement is that , the Specifier attribute has got Multiple series of values (: colon separated) i need to map each series of values to my custom java class

I tried this way

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class SampleRequest {

    @XmlAttribute
    private String user;

    @XmlAttribute
    private String account;


    @XmlAttribute(name="Specifier")
    private List<Specifier> specifier;


}

Specifier.java

@XmlJavaTypeAdapter(SpecifierAdapter.class)
public class Specifier {



}

SpecifierAdapter.java

public class SpecifierAdapter  extends XmlAdapter{

    @Override
    public Object marshal(Object arg0) throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Object unmarshal(Object arg0) throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

}

Edited part

The class Specifier has got 3 String properties .

class Specifier
{
String value1;
String value2;
String value3;
}

And i need each series of Specifier for example (value1a,value1b,value1c) should be mapped to value1 , value2 , value3 respectively

Edited Part 3

Hi , Thanks for the response , i tried to unmarshall this example , what i found is that , i am getting null

This is the request i passed

<sampleRequest user="user" account="account" Specifier="v1,v2,v3 : a1,a2,a3"/>

Just want to make sure that , is my Specifier class is correct or not ?? (As i did not use any Annotations here )

package com;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(SpecifierAdapter.class)
public class Specifier {


    Specifier(String v1 , String v2 , String v3)
    {

    }

    String value1;

    public String getValue1() {
        return value1;
    }

    public void setValue1(String value1) {
        this.value1 = value1;
    }

    public String getValue2() {
        return value2;
    }

    public void setValue2(String value2) {
        this.value2 = value2;
    }

    public String getValue3() {
        return value3;
    }

    public void setValue3(String value3) {
        this.value3 = value3;
    }

    String value2;
    String value3;

}
Unthread answered 10/8, 2012 at 13:41 Comment(4)
What are the properties of Specifier class and how they map to Specifier xml attribute?Selway
Thanks Pangea , i have edited my question to answer your query . please see .Unthread
I have edited my question ( I am getting null as result ) when unmarshalling could please let me knwo is my Specifier class is correct or not ??Unthread
I agree that i shouldn't edit or delete my previous questions , really feeling guilty after seeing Jin Kwon response . I Sincerely apologizeUnthread
S
7

NOTE: The adapter code could be made simpler by using guava-library's Joiner and Splitter.

SampleRequest

public class SampleRequest
{
    @XmlAttribute
    private String user;

    @XmlAttribute
    private String account;

    @XmlAttribute(name = "Specifier")
    @XmlJavaTypeAdapter(SpecifierAdapter.class)
    private List<Specifier> specifier;
}

Adapter

public class SpecifierAdapter extends XmlAdapter<String, List<Specifier>>
{
    @Override
    public List<Specifier> unmarshal(final String v) throws Exception
    {
        String[] values = v.split(":");
        List<Specifier> l = new ArrayList<Specifier>();
        for (String s : values)
        {
            String[] vs = s.split(",");
            l.add(new Specifier(vs[0], vs[1], vs[2]));
        }
        return l;
    }

    @Override
    public String marshal(final List<Specifier> v) throws Exception
    {
        String values = "";
        for (Specifier s : v)
        {
            values += s.getValue1() + "," + s.getValue2() + "," + s.getValue3() + " : ";
        }
        return values.length() > 0 ? values.substring(0, values.length() - 3) : values;
    }
}

Usage

public static void main(final String a[]) throws JAXBException
{
        SampleRequest r = new SampleRequest();
        r.setAccount("account");
        r.setUser("user");
        List<Specifier> sps = new ArrayList<Specifier>();
        sps.add(new Specifier("v1", "v2", "v3"));
        sps.add(new Specifier("a1", "a2", "a3"));
        r.setSpecifier(sps);

        JAXBContext jc = JAXBContext.newInstance(SampleRequest.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(r, System.out);
}

Output

<?xml version="1.0" encoding="UTF-8"?>
<sampleRequest user="user" account="account" Specifier="v1,v2,v3 : a1,a2,a3"/>
Selway answered 10/8, 2012 at 14:23 Comment(1)
Hi, Thanks a lot for this response. I am trying to unmarshal the XML and I am not getting how to implement the unmarshal method for Map<String, Object>. if possible can you please provide an example for unmarshal method mentioned within the MapAdapter class: https://mcmap.net/q/281214/-jaxb-how-to-marshall-map-into-lt-key-gt-value-lt-key-gtGenome
D
2

I've been prepared my answer with my IDE.

You removed your question(11887278) and asked again.

I thought and think that this requirement is not a good idea. I was just interested in your question because I've never do those multiple strings to an attribute.

My code is interestingly very same what Senthil Kumar explained.

Please see the full mavenized project at https://code.google.com/p/jinahya/source/browse/trunk/com.googlecode.jinahya/stackoverflow/src/main/java/com/googlecode/jinahya/stackoverflow/q11887278/

Please

package com.googlecode.jinahya.stackoverflow.q11887278;


import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.bind.annotation.adapters.XmlAdapter;


/**
 *
 * @author Jin Kwon <jinahya at gmail.com>
 */
public class SpecifierAdpater extends XmlAdapter<String, List<Specifier>> {


    @Override
    public List<Specifier> unmarshal(final String value) throws Exception {

        if (value == null) {
            return null;
        }

        final List<Specifier> bound = new ArrayList<Specifier>();
        for (String split : value.split(":")) {
            final Specifier specifier = new Specifier();
            specifier.fromString(split);
            bound.add(specifier);
        }
        return bound;
    }


    @Override
    public String marshal(final List<Specifier> bound) throws Exception {

        if (bound == null) {
            return null;
        }

        final StringBuilder builder = new StringBuilder();
        final Iterator<Specifier> specifiers = bound.iterator();
        if (specifiers.hasNext()) {
            builder.append(specifiers.next().toString());
        }
        while (specifiers.hasNext()) {
            builder.append(":");
            builder.append(specifiers.next().toString());
        }
        return builder.toString();
    }


}

Here comes 10 examples which each is marshalled an unmarshalled

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request user="user"/>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request/>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request user="user" account="account"/>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request specifiers="null,null,value3:null,value2,value3"/>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request specifiers="value1,null,value3"/>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request/>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request user="user" account="account" specifiers="value1,null,null"/>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request user="user" account="account" specifiers="null,null,null"/>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request specifiers="null,value2,value3"/>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request user="user" account="account"/>
Decision answered 10/8, 2012 at 14:39 Comment(0)
H
1

You can try the following implementation for SpecifierAdapter.java

public class SpecifierAdapter extends XmlAdapter<String, List<Specifier>>{
  @Override
  public String marshal(List<Specifier> values) throws Exception {
    StringBuilder result = new StringBuilder();
    for(Specifier specifier : values) {
      result.append(specifier.toString()); //assuming you have overridden toString() method
      result.append(",");
    }
    return result.length>0? result.substring(0, result.length() - 1): "";
  }

  @Override
  public List<Specifier> unmarshal(String colonSeparated) throws Exception {   
    List<String> values =  Arrays.asList(colonSeparated.split(":"));
    List<Specifier> specifiers = new ArrayList<Specifiers>();
    for(String str : values){
        specifiers.add(new Specifier(str)); //here use your constructor appropriately
    }
    return specifiers;
  }
}
Haynes answered 10/8, 2012 at 13:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.