0

I try to map on Java class an opennms rest api; I use a Java client correctly configured, but the jaxb unmarshall failed with error:

[org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver] (134) - Resolving exception from handler ...

This is the Java client and jaxb code:

@Override
public List<User> getUserList() {

    Client client = null;
    try {
        client = buildClient();
        final WebResource webResource = client.resource(opennmsUrl + "users");

        final ClientResponse response = webResource.get(ClientResponse.class);

        if (response.getStatus() != 200) {
            throw new IllegalStateException("Request to remote opennms server failed with error " + response.getStatus() + " : " + response.getStatusInfo().toString());
        } else {

            LOGGER.info("Response: result ({}), reason [{}]", response.getStatus(), response.getStatusInfo());
            LOGGER.info("Response: body [{}]", response.getEntity(String.class));

            final JAXBContext jaxbContext = JAXBContext.newInstance(opennmsUsersSchema);
            final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            final JAXBElement<Users> element = (JAXBElement<Users>) jaxbUnmarshaller.unmarshal(response.getEntityInputStream());
            final Users usrList = (Users) element.getValue();

            return usrList.getUser();

            /*User admin = new User();

            admin.setUserId("admin");
            admin.setFullName("Administrator");
            admin.setUserComments("Default administrator, do not delete");                
            admin.setPassword("!!opennms2015");
            admin.setTuiPin("pin");
            admin.setReadOnly(Boolean.FALSE);

            List<User> users = new ArrayList<>();

            users.add(admin);

            return users;*/
        }
    } catch (IllegalStateException e) {
        throw e;
    } catch (Exception e) {
        throw new IllegalStateException("Exception on Request", e);
    } finally {
        if (client != null) {
            client.destroy();
        }
    }
}

EDIT: Response body xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <users count="1" totalCount="1">
    <user>
      <user-id>admin</user-id>
      <full-name>Administrator</full-name>
      <user-comments>Default administrator</user-comments>
      <email></email>
      <password>123456</password>
      <passwordSalt>true</passwordSalt>
    </user>
  </users>

EDIT: Info submitted in comments

opennmsUsersSchema is the package contains the java classes auto-generated by maven jaxb plugin from xsd schemas

the xsd schema is here : xmlns.opennms.org/xsd/users

This is the Users java class :

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "", propOrder = { "user" })
@XmlRootElement(name = "users") 
public class Users { 
  @XmlElement(required = true) 
  protected List<User> user; 
  public List<User> getUser() { if (user == null) { user = new ArrayList<User>(); } return this.user; } 
}

This is the User java class :

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"userId",
"fullName",
"userComments",
"password",
"contact",
"dutySchedule",
"tuiPin"
})
@XmlRootElement(name = "user")
public class User {

@XmlElement(name = "user-id", required = true)
protected String userId;
@XmlElement(name = "full-name")
protected String fullName;
@XmlElement(name = "user-comments")
protected String userComments;
@XmlElement(required = true)
protected String password;
protected List<Contact> contact;
@XmlElement(name = "duty-schedule")
protected List<String> dutySchedule;
@XmlElement(name = "tui-pin")
protected String tuiPin;
@XmlAttribute(name = "read-only")
protected Boolean readOnly;

public String getUserId() {
    return userId;
}

public void setUserId(String value) {
    this.userId = value;
}

public String getFullName() {
    return fullName;
}

public void setFullName(String value) {
    this.fullName = value;
}

public String getUserComments() {
    return userComments;
}

public void setUserComments(String value) {
    this.userComments = value;
}

public String getPassword() {
    return password;
}

public void setPassword(String value) {
    this.password = value;
}

public List<Contact> getContact() {
    if (contact == null) {
        contact = new ArrayList<Contact>();
    }
    return this.contact;
}

public List<String> getDutySchedule() {
    if (dutySchedule == null) {
        dutySchedule = new ArrayList<String>();
    }
    return this.dutySchedule;
}

public String getTuiPin() {
    return tuiPin;
}

public void setTuiPin(String value) {
    this.tuiPin = value;
}

public boolean isReadOnly() {
    if (readOnly == null) {
        return false;
    } else {
        return readOnly;
    }
}

public void setReadOnly(Boolean value) {
    this.readOnly = value;
}

}

Jongware
  • 22,200
  • 8
  • 54
  • 100
moly
  • 11
  • 4
  • Not used to seeing this code.. JAXBContext.newInstance(opennmsUsersSchema), I would have done something like JAXBContext.newInstance(ObjectFactory.class);, but I do not know what your opennmsUsersSchema is, since its not included in code, do you have some more stacktrace, unexpected element? – Petter Friberg Nov 16 '15 at 09:40
  • opennmsUsersSchema is the package contains the java classes auto-generated by maven jaxb plugin from xsd schemas. – moly Nov 16 '15 at 09:44
  • Do you have an example of the **xml** that you are actually trying to parse.., so that I can test it. – Petter Friberg Nov 16 '15 at 13:56
  • admin Administrator Default administrator 123456 true – moly Nov 16 '15 at 14:15
  • This will not unmarshal since it does not respect xsd Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"users"). Expected elements are <{http://xmlns.opennms.org/xsd/users}contact>,<{http://xmlns.opennms.org/xsd/users}header>,<{http://xmlns.opennms.org/xsd/users}user>,<{http://xmlns.opennms.org/xsd/users}userinfo>,<{http://xmlns.opennms.org/xsd/users}users> – Petter Friberg Nov 16 '15 at 14:27
  • The tag user needs something like this and I can unmarshall it... if you have still a problem I can show you how I do... – Petter Friberg Nov 16 '15 at 14:32
  • Unfortunately I can't edit xml because I take it directly from response body by java rest client. Can you show me how do you completing unmarshall ? – moly Nov 16 '15 at 14:41
  • I have update answer, for running without namespace and with a link so you can see how its added, your choice... – Petter Friberg Nov 16 '15 at 14:56

2 Answers2

0

If the xml as in question is:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <users count="1" totalCount="1" xmlns="xmlns.opennms.org/xsd/users">
    <user>
      <user-id>admin</user-id>
      <full-name>Administrator</full-name>
      <user-comments>Default administrator</user-comments>
      <email></email>
      <password>123456</password>
      <passwordSalt>true</passwordSalt>
    </user>
  </users>

Note: I added the namespace xmlns="xmlns.opennms.org/xsd/users"

This code would unmarshall it

JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
javax.xml.bind.Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Object element = jaxbUnmarshaller.unmarshal(theXml);
if (element instanceof Users){
     System.out.println(((Users)element).getUser().get(0).getFullName());
}

where the ObjectFactory.class is in your package where you have the java classes auto-generated by maven jaxb

Note: in my package-info.java I have @javax.xml.bind.annotation.XmlSchema(namespace = "http://xmlns.opennms.org/xsd/users"), as autogenerated by jaxb

EDIT: Comment of user, xml is arriving without name space

Since the xml is not arriving with correct name space, you need to remove this from your classes or added it to the xml.

TO REMOVE IT

  1. package-info.java remove @javax.xml.bind.annotation.XmlSchema(namespace = "http://xmlns.opennms.org/xsd/users")

  2. Users.java, remove all namespace specifications

  3. User.java, remove all namespace specifications

and it will run without namespace,

TO ADD IT

To added to xml before unmarshalling see this jaxb-how-to-ignore-namespace-during-unmarshalling-xml-document

Community
  • 1
  • 1
Petter Friberg
  • 21,252
  • 9
  • 60
  • 109
0

Thanks for support ! This is the final code :

    @Override
public List<User> getUserList() {

    Client client = null;
    try {
        client = buildClient();
        final WebResource webResource = client.resource(opennmsUrl + "users");

        final ClientResponse response = webResource.get(ClientResponse.class);

        if (response.getStatus() != 200) {
            throw new IllegalStateException("Request to remote opennms server failed with error " + response.getStatus() + " : " + response.getStatusInfo().toString());
        } else {

            //LOGGER.info("Response: result ({}), reason [{}]", response.getStatus(), response.getStatusInfo());
            //LOGGER.info("Response: body [{}]", response.getEntity(String.class));

            //Prepare JAXB objects
            JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

            //Create an XMLReader to use with our filter
            XMLReader reader = XMLReaderFactory.createXMLReader();

            //Create the filter (to add namespace) and set the xmlReader as its parent.
            NamespaceFilter inFilter = new NamespaceFilter("http://xmlns.opennms.org/xsd/users", true);
            inFilter.setParent(reader);

            //Prepare the input, in this case a java.io.File (output)
            InputSource is = new InputSource(response.getEntityInputStream());

            //Create a SAXSource specifying the filter
            SAXSource source = new SAXSource(inFilter, is);

            //Do unmarshalling
            Object element = jaxbUnmarshaller.unmarshal(source);

            if (element instanceof Users) {
                //System.out.println(((Users) element).getUser().get(0).getFullName());
                return ((Users) element).getUser();
            }
        }
    } catch (IllegalStateException e) {
        throw e;
    } catch (NoSuchAlgorithmException | KeyManagementException | UniformInterfaceException | ClientHandlerException | JAXBException e) {
        throw new IllegalStateException("Exception on Request", e);
    } catch (SAXException ex) {
        java.util.logging.Logger.getLogger(OpennmsRemote.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        if (client != null) {
            client.destroy();
        }
    }
    return null;
}

}

moly
  • 11
  • 4