ClassCastException while extracting data from List - java

This is my XML file :-
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<logExtract>
<configuration>
<splunk>
<splunkHost>localhost</splunkHost>
<userName>abcd</userName>
<password>1234</password>
<port>8214</port>
</splunk>
<tsdb>
<tsdbHost>localhsot</tsdbHost>
<port>4242</port>
</tsdb>
</configuration>
<dataPart>
<ingestion id="abc">
<tsdbElements>
<metricname>linecount0</metricname>
<tags>splunk_server0</tags>
</tsdbElements>
<splunkQuery>
<Query>index=_internal source=*/splunkd_access.log |head 0000</Query>
</splunkQuery>
</ingestion>
<ingestion id="xyz">
<tsdbElements>
<metricname>linecount</metricname>
<tags>splunk_server</tags>
</tsdbElements>
<splunkQuery>
<query>index=_internal source=*/splunkd_access.log |head 1000</query>
</splunkQuery>
</ingestion>
<ingestion id="def">
<tsdbElements>
<metricname>linecount2</metricname>
<tags>splunk_server2</tags>
</tsdbElements>
<splunkQuery>
<query>index=_internal source=*/splunkd_access.log |head 2000</query>
</splunkQuery>
</ingestion>
</dataPart>
</logExtract>
I have used JAXB and created POJO class structure for it.
For Ingestion element this is my POJO class structure.
private String id;
private List<TsdbElements> TsdbElements;
private List<SplunkQuery> SplunkQuery;
#XmlAttribute
public String getId ()
{
return id;
}
public void setId (String id)
{
this.id = id;
}
#XmlElement
public List<TsdbElements> getTsdbElements ()
{
return TsdbElements;
}
public void setTsdbElements (List<TsdbElements> TsdbElements)
{
this.TsdbElements = TsdbElements;
}
#XmlElement
public List<SplunkQuery> getSplunkQuery ()
{
return SplunkQuery;
}
public void setSplunkQuery (List<SplunkQuery> SplunkQuery)
{
this.SplunkQuery = SplunkQuery;
}
#Override
public String toString()
{
return "ClassPojo [id = "+id+", TsdbElements = "+TsdbElements+", SplunkQuery = "+SplunkQuery+"]";
}
Here is the Problem :-
When I try to extract Objects of ingestion I get error
(java.util.ArrayList cannot be cast to com.jaxb.xmlfile.Ingestio) java.lang.ClassCastException
at line below comment.
String fileName = "Query.xml";
File file = new File(fileName);
//JAXB Parsing - Unmarshling XML File
JAXBContext jaxbContext = JAXBContext.newInstance(XMLData.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
LogExtract logExtract = (LogExtract) jaxbUnmarshaller.unmarshal(file);
Configuration config = logExtract.getConfiguration();
Splunk spluknData = config.getSplunk();
Tsdb tsdbData = config.getTsdb();
DataPart dataPart = logExtract.getDataPart();
List<Ingestion> ingestionData = dataPart.getIngestion();
//Here I get Error
List<TsdbElements> tsdbElementsData = ((Ingestion) ingestionData).getTsdbElements();
//Here I get Error
List<SplunkQuery> splunkQueryData = ((Ingestion) ingestionData).getSplunkQuery();
System.out.println(spluknData.getSplunkHost() + " " + spluknData.getUserName() + " " + spluknData.getPassword() + " " +spluknData.getPort());
System.out.println(tsdbData.getTsdbHost() + " " + tsdbData.getPort());
for (SplunkQuery splunkQuery : splunkQueryData) {
System.out.println(splunkQuery.getQuery());
}
for (TsdbElements tsdbElements : tsdbElementsData) {
System.out.println(tsdbElements.getMetricname() + " " + tsdbElements.getTags());
}
So what am I missing?
EDIT:- (After answer given by #Sanj)
How to save tsdbElement data using for loop and then access them again out of for loop? Any Idea? Because its only saving last XML data, not all of them

List<Ingestion> ingestionData = dataPart.getIngestion();
//Here I get Error
List<TsdbElements> tsdbElementsData = ((Ingestion) ingestionData).getTsdbElements();
The error is stating that ingestionData is a type List, and you are trying to cast it to the Ingestion class.
Looking at your XML, you have a list of of these elements
<ingestion id="abc">
<tsdbElements>
<metricname>linecount0</metricname>
<tags>splunk_server0</tags>
</tsdbElements>
<splunkQuery>
<Query>index=_internal source=*/splunkd_access.log |head 0000</Query>
</splunkQuery>
</ingestion>
So you just need to iterate the list ingestionData to get the tsdbElements. Something like
// instantiate the tsdbElementsData list
List<TsdbElements> tsdbElementsData = new ArrayList<>(TsdbElements)
for (Ingestion ingestion: ingestionData)
{
// get the elements
tsdbElements = ingestion.getTsdbElements();
// do some with the elements, e,g add to a another list
tsdbElementsData.add(tsdbElements);
}
To iterate through the tsdbElementsData list, it is just another loop
for (TsdbElements tsdbElements: tsdbElementsData)
{
// ... do something with tsdbElements
}
Note that the foreach loop above, is the same a writing
for (int i = 0; i < tsdbElementsData.size(); i++)
{
TsdbElements tsdbElements = tsdbElementsData.get(i);
// ... do something with tsdbElements
}

Related

How to Solve Deserialization error ask sdk

I'm attempting to convert the JSON output from my session and map it to a class that I've created using JAVA's ObjectMapper. When I run my tests on Lambda I get a Deserialisation error:
Deserialization error: com.amazon.ask.exception.AskSdkException
com.amazon.ask.exception.AskSdkException: Deserialization error
at com.amazon.ask.util.impl.JacksonJsonUnmarshaller.unmarshall(JacksonJsonUnmarshaller.java:50)
at com.amazon.ask.impl.AbstractSkill.execute(AbstractSkill.java:44)
at com.amazon.ask.AlexaSkill.execute(AlexaSkill.java:22)
at com.amazon.ask.SkillStreamHandler.handleRequest(SkillStreamHandler.java:71)
Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'AnswerIntent' as a subtype of [simple type, class com.amazon.ask.model.Request]: known type ids = [Alexa.Presentation.APL.UserEvent, AlexaHouseholdListEvent.ItemsCreated, AlexaHouseholdListEvent.ItemsDeleted, AlexaHouseholdListEvent.ItemsUpdated, AlexaHouseholdListEvent.ListCreated, AlexaHouseholdListEvent.ListDeleted, AlexaHouseholdListEvent.ListUpdated, AlexaSkillEvent.SkillAccountLinked, AlexaSkillEvent.SkillDisabled, AlexaSkillEvent.SkillEnabled, AlexaSkillEvent.SkillPermissionAccepted, AlexaSkillEvent.SkillPermissionChanged, AudioPlayer.PlaybackFailed, AudioPlayer.PlaybackFinished, AudioPlayer.PlaybackNearlyFinished, AudioPlayer.PlaybackStarted, AudioPlayer.PlaybackStopped, Connections.Request, Connections.Response, Display.ElementSelected, GameEngine.InputHandlerEvent, IntentRequest, LaunchRequest, Messaging.MessageReceived, PlaybackController.NextCommandIssued, PlaybackController.PauseCommandIssued, PlaybackController.PlayCommandIssued, PlaybackController.PreviousCommandIssued, SessionEndedRequest, System.ExceptionEncountered] (for POJO property 'request')
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.amazon.ask.model.RequestEnvelope$Builder["request"])
at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43)
at com.fasterxml.jackson.databind.DeserializationContext.invalidTypeIdException(DeserializationContext.java:1628)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownTypeId(DeserializationContext.java:1186)
at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._handleUnknownTypeId(TypeDeserializerBase.java:291)
at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:162)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:113)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:97)
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:254)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeSetAndReturn(MethodProperty.java:151)
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.vanillaDeserialize(BuilderBasedDeserializer.java:269)
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserialize(BuilderBasedDeserializer.java:193)
at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:3972)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2264)
at com.fasterxml.jackson.databind.ObjectMapper.treeToValue(ObjectMapper.java:2746)
at com.amazon.ask.util.impl.JacksonJsonUnmarshaller.unmarshall(JacksonJsonUnmarshaller.java:48)
... 3 more
I did checks to ensure that my "riddleItem" variable is not null. The JSON values are being mapped to the Person class which just returns properties of a person. The code is shown below and I've highlighted the line which the error occurs on:
public Optional<Response> handle(HandlerInput input) {
Map<String, Object> sessionAttributes = input.getAttributesManager().getSessionAttributes();
System.out.println("This a FIRST debug");
LOG.debug("This a FIRST debug");
boolean correctAnswer;
String speechText = null, response;
System.out.println("This a SECOND debug");
Map<String, String> riddleItem = (LinkedHashMap<String, String>)sessionAttributes.get(Attributes.RIDDLE_ITEM_KEY);
Person person;
// System.out.println("riddleItem " + riddleItem);
if(riddleItem != null)
{
person = MAPPER.convertValue(riddleItem, Person.class); // ERROR OCCURS ON THIS LINE
}
System.out.println("This a THIRD debug");
PersonProperty personProperty = PersonProperty.valueOf((String) sessionAttributes.get(Attributes.RIDDLE_PROPERTY_KEY));
int counter = (int) sessionAttributes.get(Attributes.COUNTER_KEY);
int riddleGameScore = (int) sessionAttributes.get(Attributes.RIDDLE_SCORE_KEY);
System.out.println("This a FOURTH debug");
IntentRequest intentRequest = (IntentRequest) input.getRequestEnvelope().getRequest();
correctAnswer = compareSlots(intentRequest.getIntent().getSlots(), getPropertyOfPerson(personProperty, person));
System.out.println("This a FIFTH debug " + correctAnswer);
if(correctAnswer)
{
riddleGameScore++;
response = getSpeechExpressionCon(true);
System.out.println("This a SIXTH debug " + response);
sessionAttributes.put(Attributes.RIDDLE_SCORE_KEY, riddleGameScore);
}
else
{
response = getSpeechExpressionCon(false);
System.out.println("This a SEVENTH debug " + response);
}
AnswerIntentHandler setup = new AnswerIntentHandler();
//
if(riddle.getAnswer() != null)
{
speechText = "Hello " + riddle.getAnswer();
}
return input.getResponseBuilder()
.withSimpleCard("RiddleSession", speechText)
.withSpeech(speechText)
.withShouldEndSession(true)
.build();
}
[Json Output of properties under "riddleItem" during Session]1
I know my the values being mapped aren't empty thus I'm at a complete loss of ideas as to what's going on as I've come up short with possible ideas as to what the problem might be.
I solved the problem as I came to realise that when mapping from JSON to a class, methods ('set' methods) for assigning the JSON values to the variables in the class must be created. A sample structure for example:
public class State {
public State() {}
public State(String name, String abbreviation, String capital, String statehoodYear, String statehoodOrder) {
this.name = name;
this.abbreviation = abbreviation;
this.capital = capital;
this.statehoodYear = statehoodYear;
this.statehoodOrder = statehoodOrder;
}
public String getName() {
return name;
}
public String getAbbreviation() {
return abbreviation;
}
public String getCapital() {
return capital;
}
public String getStatehoodYear() { return statehoodYear; }
public String getStatehoodOrder() {
return statehoodOrder;
}
public void setName(String name) {
this.name = name;
}
public void setAbbreviation(String abbreviation) {
this.abbreviation = abbreviation;
}
public void setCapital(String capital) {
this.capital = capital;
}
public void setStatehoodYear(String statehoodYear) {
this.statehoodYear = statehoodYear;
}
public void setStatehoodOrder(String statehoodOrder) {
this.statehoodOrder = statehoodOrder;
}
}
The declaration of an empty constructor is necessary when making use of multiple constructors where, one is parametric. In some cases without the inclusion of such constructor an error may be thrown so, to avoid the possibility of said error, adding the constructor as a "Dummy" so to say, is essential.

Unique Validation In Broadleaf

I am trying to add a unique validation on a field while adding a product on Broadleaf. Currently we have added a 'SKU' field while adding product from admin screen. I have used the following annotation to validate:
#AdminPresentationMergeOverride(name = "userSku", mergeEntries = #AdminPresentationMergeEntry(propertyType = PropertyType.AdminPresentation.VALIDATIONCONFIGURATIONS, validationConfigurations = {
#ValidationConfiguration(validationImplementation = "blUniqueValueValidator", configurationItems = {
#ConfigurationItem(itemName = "otherField", itemValue = "userSku") }) })
It works perfect when we try to add a new product.
But the problem is, If I try to update any product to change any field, it gives the same validation error
Looks like that doesn't work quite right, can you open an issue in https://github.com/BroadleafCommerce/Issues?
You can also write your own uniqueness validates that does not run into the same ID problem like so:
#Component
public class MyUniqueValueValidator implements PropertyValidator {
protected static final Log LOG = LogFactory.getLog(UniqueValueValidator.class);
#Override
public PropertyValidationResult validate(Entity entity,
Serializable instance,
Map<String, FieldMetadata> entityFieldMetadata,
Map<String, String> validationConfiguration,
BasicFieldMetadata propertyMetadata,
String propertyName,
String value) {
String instanceClassName = instance.getClass().getName();
DynamicEntityDao dynamicEntityDao = getDynamicEntityDao(instanceClassName);
List<Long> responseIds = dynamicEntityDao.readOtherEntitiesWithPropertyValue(instance, propertyName, value);
String message = validationConfiguration.get(ConfigurationItem.ERROR_MESSAGE);
if (message == null) {
message = entity.getType()[0] + " with this value for attribute " +
propertyName + " already exists. This attribute's value must be unique.";
}
boolean onlyInCurrentEntity = CollectionUtils.isEmpty(responseIds)
|| (responseIds.size() == 1 && responseIds.get(0).equals(getDynamicEntityDao(instanceClassName).getIdentifier(instance)));
return new PropertyValidationResult(onlyInCurrentEntity, message);
}
protected DynamicEntityDao getDynamicEntityDao(String className) {
return PersistenceManagerFactory.getPersistenceManager(className).getDynamicEntityDao();
}
}
And then use the validator by passing in the bean ID to the validationImplementation:
#AdminPresentationMergeOverride(name = "userSku", mergeEntries = #AdminPresentationMergeEntry(propertyType = PropertyType.AdminPresentation.VALIDATIONCONFIGURATIONS, validationConfigurations = {
#ValidationConfiguration(validationImplementation = "myUniqueValidator", configurationItems = {
#ConfigurationItem(itemName = "otherField", itemValue = "userSku") }) })

Jaxb Giving null on Unmarshalling nested Soap Message

I need to unmarshall nested soap response to java object using jaxb. But i am always getting a null pointer exception.
I have checked almost all links out there like the following:
jaxb unmarshalling returns null
jaxb unmarshalling giving NULL to anytype element in xsd
But nothing worked out for me.
Here is my soap response message
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsap.org/sap/env/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<soapenv:Body>
<ns1:subscribeProductResponse xmlns:ns1='http://www.csapi.org/schema/parlayx/subscribe/manage/v1_0/local'>
<ns1:subscribeProductRsp>
<result>22007233</result>
<resultDescription>Temporary Order saved successfully! DataSendStep finish end.</resultDescription>
</ns1:subscribeProductRsp>
</ns1:subscribeProductResponse>
</soapenv:Body>
</soapenv:Envelope>
Here are my Java Pojo Classes
#XmlRootElement (name="subscribeProductResponse",namespace="http://www.csapi.org/schema/parlayx/subscribe/manage/v1_0/local")
#XmlAccessorType(XmlAccessType.FIELD)
public class SubscribeProductResponse {
// #XmlElementWrapper
#XmlElement(name="subscribeProductRsp")
private SubscribeProductRsp subscribeProductRsp;
public SubscribeProductRsp getSubscribeProductRsp() {
return subscribeProductRsp;
}
public void setSubscribeProductRsp(SubscribeProductRsp subscribeProductRsp) {
this.subscribeProductRsp = subscribeProductRsp;
}
}
#XmlRootElement(name="subscribeProductRsp")
public class SubscribeProductRsp {
private String result;
private String resultDescription;
public String getResult() {
return result;
}
#XmlElement(name = "result", required = true)
public void setResult(String result) {
this.result = result;
}
public String getResultDescription() {
return resultDescription;
}
#XmlElement(name = "resultDescription", required = true)
public void setResultDescription(String resultDescription) {
this.resultDescription = resultDescription;
}
#Override
public String toString() {
return "ClassPojo [result = " + result + ", resultDescription = "
+ resultDescription + "]";
}
}
Below is the code to unmarshal the response message
JAXBContext jc = JAXBContext.newInstance(SubscribeProductResponse.class);
Unmarshaller um = jc.createUnmarshaller();
SubscribeProductResponse output = (SubscribeProductResponse)um.unmarshal(soapResponse.getSOAPBody().extractContentAsDocument());
System.out.println(output.getSubscribeProductRsp().getResult());
JAXBContext jc = JAXBContext.newInstance(SubscribeProductResponse.class);
Unmarshaller um = jc.createUnmarshaller();
SubscribeProductResponse output = (SubscribeProductResponse)um.unmarshal(soapResponse.getSOAPBody().extractContentAsDocument());
System.out.println(output.getSubscribeProductRsp().getResult());
I am getting output.getSubscribeProductRsp() as null
Can anyone please tell me what i am doing wrong.

How to format xml instead of original format in springMVC (Restful webservice)

Currently, I want to return the return xml result with XML with the below format :
I tried to use something like this
#XmlRootElement(name = "item")
public class Book implements Serializable {
#XmlAttribute
public int getBookId() {
return bookId;
}
...
....
and
#XmlRootElement(name = "OneBoxResults")
public class JavaClazz {
private List<Book> OneBoxResults;
public List<Book> getOneBoxResults() {
return OneBoxResults;
}
#XmlElements(#XmlElement(name = "book", type = Book.class))
public void setOneBoxResults(List<Book> oneBoxResults) {
OneBoxResults = oneBoxResults;
}
...
However, the return result which I received is only Json format as below :
{"oneBoxResults":[{"bookId":1,"bookName":"Search
Deployment","update":"2014-01-07","description":"A successful deployment
typically involves the following
elements:","path":null},{"bookId":2,"bookName":"GSA
Information","update":"2015-01-07","description":"Configure the OneBox
module so it sends search queries to the provider (a custom
application","path":null}]}
I also attemped to create new format in controller as below :
#RequestMapping(value = "/rest.oneboxSample",produces = MediaType.APPLICATION_XML_VALUE, method = RequestMethod.GET)
public #ResponseBody String oneboxSample(){
String tmpOpenField = "<Field name=\"";
String tmpCloseField = "</Field>";
StringBuilder builder = new StringBuilder();
builder.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
builder.append("<OneBoxResults>").append("<resultCode>");
builder.append("Listbook").append("<resultCode>");
for(int i = 0; i < bookDao.getBooks().size(); i++){
Book tmpBook = bookDao.getBooks().get(i);
builder.append("<MODULE_RESULT>");
builder.append(tmpOpenField).append("bookId\">").append(tmpBook.getBookId()).append(tmpCloseField);
builder.append(tmpOpenField).append("bookName\">").append(tmpBook.getBookName()).append(tmpCloseField);
builder.append(tmpOpenField).append("update\">").append(tmpBook.getUpdate()).append(tmpCloseField);
builder.append(tmpOpenField).append("description\">").append(tmpBook.getDescription()).append(tmpCloseField);
builder.append(tmpOpenField).append("path\">").append(tmpBook.getPath()).append(tmpCloseField);
builder.append("</MODULE_RESULT>");
}
builder.append("</OneBoxResults>");
return builder.toString();
}
But the result is not good. It returned a string instead of xml format which we need.
Now, our system need to receive a xml format instead of an original xml format.
Please tell me know the way to do it .
The below is my source code which I wrote
https://www.dropbox.com/s/4tyg0kp7gkzodod/onebox-service.zip?dl=0
Thanks,

Simple framework skip soap envelope and body

I'm using RetroFit and Simple XML Framework in Android to model a SOAP response that looks like this:
XML:
<soap:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<BuslocationResponse
xmlns="AT_WEB">
<Version>1.0</Version>
<Responsecode>0</Responsecode>
<Input>
<Route>801</Route>
<Direction>N</Direction>
</Input>
<Vehicles>
<Vehicle>
<Route>801</Route>
<Direction>N</Direction>
<Updatetime>09:42 PM</Updatetime>
<Vehicleid>5007</Vehicleid>
<Block>801-06</Block>
<Adherance>-2</Adherance>
<Adhchange>S</Adhchange>
<Reliable>Y</Reliable>
<Offroute>N</Offroute>
<Stopped>N</Stopped>
<Inservice>Y</Inservice>
<Speed>20.61</Speed>
<Heading> 3</Heading>
<Routeid>44916</Routeid>
<Positions>
<Position>30.221222,-97.765007</Position>
<Position>30.218363,-97.766747</Position>
<Position>30.215282,-97.768715</Position>
<Position>30.212505,-97.770485</Position>
<Position>30.204943,-97.774765</Position>
<Position>30.204035,-97.775078</Position>
</Positions>
</Vehicle>
</Vehicles>
</BuslocationResponse>
</soap:Body>
</soap:Envelope>
Really, all I care about is the collection of vehicles. It seems like I could model just the BusLocationResponse and skip the soap envelope and body by declaring the
Java:
#Root(strict=false)
#Path("Envelope/Body/BuslocationResponse")
public class BusLocationResponse {
#Element(name="Responsecode")
public int responseCode;
#ElementList
#Path("Envelope/Body/BuslocationResponse/Vehicles")
public List<CapVehicle> vehicles;
}
This just yields the error:
org.simpleframework.xml.core.ValueRequiredException: Unable to satisfy
#org.simpleframework.xml.Element(data=false, name=Responsecode, required=true,
type=void) on field 'responseCode'
What am I misunderstanding here?
You can't use #Path on #Root-Element:
The Path annotation is used to specify an XML path where an XML element or attribute is located.
( Source )
Since you want nested data, from somewhere deep in the xml, there are two solutions:
Map the whole XML structure
Use a Converter that cut's mapping down to few classes and map just those
And here's what to do if you choose No. 2:
The Plan
A SOAPEnvelope class builds just the root-element (<soap:Envelope>...</soap:Envelope>) and holds the list of vehicles
A SOAPEnvelopeConverter implements a Converter for SOAPEnvelope - there the serialization is reduced to vehicles list only
A class Vehicle holds all the data of those elements (incl. a class Position for the <Position>...</Position> elements)
A class Vehicles maps the vehicles-tag only (= list of vehicle elements).
(Names have no convention)
The Implementation
I've written an implementation as a reference so you can see how my suggested solution works. Please add error checking etc. All data fields are handled as String's here, replace their types with proper ones. Only the vehicles list is deserialized, all other values are ignored. Constructors, getter / setter etc. are only shown as they are required for this example.
The deserialized vehicles list is stored into the envelope's object. This is not the best way and used for example only. Please write a better implementation here (eg. introduce a class for the soap body where you can manage contents).
Note: Some classes are implemented as inner classes - this is optional, code as you prefer.
Class SOAPEnvelope / Class SOAPEnvelopeConverter (inner)
#Root(name = "Envelope")
#Namespace(prefix = "soap")
// Set the converter that's used for serialization
#Convert(value = SOAPEnvelope.SOAPEnvelopeConverter.class)
public class SOAPEnvelope
{
// Keep the content of vehicles list here
private Vehicles vehicles;
public Vehicles getVehicles()
{
return vehicles;
}
protected void setVehicles(Vehicles vehicles)
{
this.vehicles = vehicles;
}
// The converter implementation for SOAPEnvelope
public static class SOAPEnvelopeConverter implements Converter<SOAPEnvelope>
{
#Override
public SOAPEnvelope read(InputNode node) throws Exception
{
SOAPEnvelope envelope = new SOAPEnvelope();
InputNode vehiclesNode = findVehiclesNode(node); // Search the Vehicles list element
if( vehiclesNode == null )
{
// This is bad - do something useful here
throw new Exception("No vehicles node!");
}
/*
* A default serializer is used to deserialize the full node. The
* returned object is set into the envelops's object, where you can
* get it through a get()-method.
*/
Serializer ser = new Persister();
envelope.setVehicles(ser.read(Vehicles.class, vehiclesNode));
return envelope;
}
#Override
public void write(OutputNode node, SOAPEnvelope value) throws Exception
{
// If you read (deserialize) only there's no need to implement this
throw new UnsupportedOperationException("Not supported yet.");
}
private InputNode findVehiclesNode(InputNode rootNode) throws Exception
{
InputNode body = rootNode.getNext("Body");
InputNode buslocationResponse = body.getNext("BuslocationResponse");
InputNode next;
while( ( next = buslocationResponse.getNext() ) != null )
{
if( next.getName().equals("Vehicles") == true )
{
return next;
}
}
return null;
}
}
}
Class Vehicles
#Root(name = "Vehicles")
public class Vehicles
{
// Maps the list of vehicles
#ElementList(name = "Vehicles", inline = true)
private List<Vehicle> vehicles;
}
Class Vehicle
#Root(name = "Vehicle")
public class Vehicle
{
// All values are of type String - please replace with proper types
#Element(name = "Route")
private String route;
#Element(name = "Direction")
private String direction;
#Element(name = "Updatetime")
private String updateTime;
#Element(name = "Vehicleid")
private String vehicleID;
#Element(name = "Block")
private String block;
#Element(name = "Adherance")
private String adherance;
#Element(name = "Adhchange")
private String adhchange;
#Element(name = "Reliable")
private String reliable;
#Element(name = "Offroute")
private String offroute;
#Element(name = "Stopped")
private String stopped;
#Element(name = "Inservice")
private String inservice;
#Element(name = "Speed")
private String speed;
#Element(name = "Heading")
private String heading;
#Element(name = "Routeid")
private String routeID;
#ElementList(name = "Positions")
private List<Position> postions;
// A class to map the position elements
#Root(name = "Position")
public static class Position
{
#Text()
private String position;
}
}
How to use
final String xml = ...
Serializer ser = new Persister(new AnnotationStrategy()); // Annotation strategy is set here!
SOAPEnvelope soapEnvelope = ser.read(SOAPEnvelope.class, new StringReader(xml));
Nothing special here - only AnnotationStrategy is required! The source (2nd parameter of ser.read() is set as your input comes. In this example, the soap xml comes from a string.
the simple way is use #path , example i want get Route from node Soap/Body/BuslocationResponse/Vehicles/Vehicle
Response.java
#Root(name = "soap:Envelope", strict = false)
public class Response {
#Element(name = "Route")
#Path("Body/BuslocationResponse/Vehicles/Vehicle")
private int route;
public int getRoute() {
return route;
}
}
Main.java
class Main {
public static void main(String args[]) {
String xml = "<soap:Envelope \n" +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
"xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"\n" +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
"soap:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"\n" +
"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
"<soap:Body>\n" +
" <BuslocationResponse \n" +
" xmlns=\"AT_WEB\">\n" +
" <Version>1.0</Version>\n" +
" <Responsecode>0</Responsecode>\n" +
" <Input>\n" +
" <Route>801</Route>\n" +
" <Direction>N</Direction>\n" +
" </Input>\n" +
" <Vehicles>\n" +
" <Vehicle>\n" +
" <Route>801</Route>\n" +
" <Direction>N</Direction>\n" +
" <Updatetime>09:42 PM</Updatetime>\n" +
" <Vehicleid>5007</Vehicleid>\n" +
" <Block>801-06</Block>\n" +
" <Adherance>-2</Adherance>\n" +
" <Adhchange>S</Adhchange>\n" +
" <Reliable>Y</Reliable>\n" +
" <Offroute>N</Offroute>\n" +
" <Stopped>N</Stopped>\n" +
" <Inservice>Y</Inservice>\n" +
" <Speed>20.61</Speed>\n" +
" <Heading> 3</Heading>\n" +
" <Routeid>44916</Routeid>\n" +
" <Positions>\n" +
" <Position>30.221222,-97.765007</Position>\n" +
" <Position>30.218363,-97.766747</Position>\n" +
" <Position>30.215282,-97.768715</Position>\n" +
" <Position>30.212505,-97.770485</Position>\n" +
" <Position>30.204943,-97.774765</Position>\n" +
" <Position>30.204035,-97.775078</Position>\n" +
" </Positions>\n" +
" </Vehicle>\n" +
" </Vehicles>\n" +
"</BuslocationResponse>\n" +
"</soap:Body>\n" +
"</soap:Envelope>";
try {
Serializer serializer = new Persister();
Response r = serializer.read(Response.class, xml);
System.out.println("route: " + r.getRoute());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Result:
/usr/lib/jvm/java-8-oracle/bin/java....
route: 801
Process finished with exit code 0

Categories