Have got an epic REST API with the XML response type that has an unwrapped collection of objects at the root element.
It looks like this:
<root>
<carName>Car1</carName>
<carNumber>1</carNumber>
<carType>SAV1</carType>
<carName>Car2</carName>
<carNumber>2</carNumber>
<carType>SAV2</carType>
<carName>Car3</carName>
<carNumber>3</carNumber>
<carType>SAV3</carType>
<count>3</count>
</root>
I'm trying to unmarshal this as a List of child Car objects:
#XmlRootElement
public Root {
#XmlElement
private List<Car> cars;
#XmlElement(name = "count")
private Integer count;
...
}
... where the Car is the simple jaxb bean with #XmlElement(name = "...") annotation per the each it's primitive typed field. However, all the fields except of count are null.
Have tried to use the construction like this instead of nameless #XmlElement:
#XmlElements({
#XmlElement(name = "carName", type = String.class),
#XmlElement(name = "carNumber", type = Integer.class),
#XmlElement(name = "carType", type = String.class)
})
... now I've got a 9 items array instead of 3, where's the each field of child Car class is stored as an independent array item.
So, the question is how to unmarshall XML structure like this to the well presented POJO List?
Related
Json to GraphQLArgumetn object conversion failing in graphql-spqr.
tried adding GraphQLInterface(with autodiscovery true and scanpackage) to above abstract classes
and GraphQLtype type all concrete classes.
My graph query:
query contactsQuery($searchQuery : QueryInput) { contacts(searchQuery:$searchQuery){id}}
variables:{"searchQuery":{"bool":{"conditions":[{"must":{"matches":[{"singleFieldMatch":{"boost":null,"field":"firstname","value":"siddiq"}}],"bool":null}}]}})
Java code:
#JsonTypeInfo(use=JsonTypeInfo.Id.NAME,include=JsonTypeInfo.As.WRAPPER_OBJECT)
#JsonSubTypes({#type(value = Must.class, name="must"),#type(value = MustNot.class, name="mustNot")})
public abstract class Condition
#JsonTypeInfo(use=JsonTypeInfo.Id.NAME,include=JsonTypeInfo.As.WRAPPER_OBJECT)
#JsonSubTypes({#type(value = SingleFieldMatch.class, name="singleFieldMatch"),#type(value = MultiFieldMatch.class, name="multiFieldMatch")})
public abstract class Match
#GraphQLQuery(name = "contacts")
public List getContacts(#GraphQLArgument(name ="searchQuery") Query query)
Still it's throwing error unknown field error etc. Not sure which configuration is missing.
Building GraphQLSchema with AnnotatedResolvedBuilder, base package configured JacksonValueMappperFactory and singleton services.
Hi this may be a similar issue to what I ended up having.
Initially I had the following
#JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
#GraphQLInterface(name = "AbstractClass", implementationAutoDiscovery = true)
public abstract class AbstractClass{
with the following query called
addNewObject(object: {name: "soft2", id: "asdas"})
To get conversion functioning what I needed to do was the following change
#JsonTypeInfo(use = Id.NAME, include = As.EXISTING_PROPERTY, property = "type")
#GraphQLInterface(name = "AbstractClass", implementationAutoDiscovery = true)
public abstract class AbstractClass{
private String type = this.getClass().getSimpleName();
/**
* #return the type
*/
#GraphQLQuery(name = "type", description = "The concrete type of the node. This should match the initialised class. E.g. \"Concrete\", \"DecafCoffee\"")
public String getType() {
return type;
}
with the query now being
addNewConcreteObject(concrete: {name: "soft2", id: "asdas", type: "Concrete"})
Why this worked (I think):
When converting from JSON to objects in my code using the Jackson converter (ObjectMapper). I had previously noticed that the JSON required knowledge of what class to convert to. Thus the initial use of #JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type") put a type property in the JSON when it was written to string.
The inclusion of the #JSON tag may be picked up by SPQR and it then seems to use a Jackson converter to try to convert your query to the required object.
If I am right, here is the issue.
As the query doesn't contain type the query can not be correctly converted. Moreover as the type property was not a member variable of the object but was instead only added by the ObjectMapper, SPQR didn't pick it up and so it wasn't part of the schema for the object. Thus to get around it, I added type as a member variable which is always equal to the actual class, then changed my JsonTypeInfo to look for an existing property.
I appreciate this isn't a direct answer to your question (and definitely isn't a pretty answer), but hopefully it will help you find your solution.
Let's say we have an Object A defined like this:
public class ObjectA {
private Attribute a1;
private Attribute a2;
private Attribute a3;
}
For some reason, I need to create a second object B with only the first two attriutes of the Object A :
public class ObjectB {
private Attribute a1;
private Attribute a2;
}
So my question is: what is the best approach to copy an Object A to an Object B ?
I've been copying the attributes by getters and setters one by one but something tells me there must be a better way to do this ! Especially when the object will have a lot of attributes, I have to write lines and lines of code just to copy all of them to the second Object B ...
Thanks a lot :)
EDIT: I've been being alerted by a "possible duplicate of another question" : How do I copy an object in Java?
My question is slightly different in a way that I'm dealing with 2 different objects who just share the same attributes but not totally !
Try libraries like Dozer or BeanUtils
To expand on my comment:
Using Dozer it can be as easy as:
Mapper mapper = new DozerBeanMapper();
ObjectA source = new ObjectA();
ObjectB target = mapper.map(source , ObjectB.class);
or if your target class doesn't have a no-arg constructor:
ObjectA source = new ObjectA();
ObjectB target = new ObjectB(/*args*/);
mapper.map(source, target );
From the Documentation (emphasis by me):
After performing the Dozer mapping, the result will be a new instance of the destination object that contains values for all fields that have the same field name as the source object. If any of the mapped attributes are of different data types, the Dozer mapping engine will automatically perform data type conversion.
What you need is Object mappers. Try Orika or Dozer.
The objects need not be of the same type. While mapping if it finds the attributes of the same name and type, it automatically maps it.
MapperFacade mapper = mapperFactory.getMapperFacade();
UserDTO userDTO = new UserDTO();
userDTO.setName("xyz");
..
User user = mapper.map(userDTO, User.class);
You can also customize if you have to map different attribute names.
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(UserDTO.class, User.class)
.field("name", "username")
.byDefault().register();
mapper = mapperFactory.getMapperFacade();
...
User user = mapper.map(userDTO, User.class);
Given a Hibernate Entity Foo
#Entity
#Table(name = "foo")
class Foo {
//ID Field
#Column(name = "bar", nullable = false)
#Enumerated(EnumType.STRING)
private Bar bar;
//Getters, Setters
}
And an Enum Bar
enum Bar {
CAT,
CRADLE,
SILVER,
SPOON;
}
I would like to run a query checking if Foo.bar's value contains some String matchString = "ADL".
Currently, my DetachedCriteria object is constructed as:
DetachedCriteria.forClass(Foo.class)
.add(Restrictions.like("bar", matchString, MatchMode.ANYWHERE));`
but causes a java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Enum when invoked.
A query like this would only be possible if the enum is persisted using the String value rather than the ordinal - but even then I would not expect the criteria API to necessarily support a like for enums.
Instead of trying to do the like at the database level you can find all the enums where the name contains "bar" (in Java code) and then query for all the matches where "bar" is in that set. This is similar to https://stackoverflow.com/a/18899529/4248600.
Disjunction or = Restrictions.disjunction();
for (BarEnum bar : BarEnum.values()) {
if (bar.name().contains(matchStr)) {
or.add(Restrictions.eq("bar", bar));
}
}
criteria.add(or);
How to get a list of Object, where the tla (three letter acronym) of an LoanboardEmployee equals the providedTla inside the list of borrowers inside the list of ActionStamps (preferably the last stamp)?
I have the following classes:
Object:
#Id
private String objectCode;
#Embedded
private List<ActionStamp> borrowingHistory;
...
ActionStamp (used in Object)
#Reference
private LoanboardEmployee responsible;
#Reference
private List<LoanboardEmployee> borrowers;
...
LoanboardEmployee (used in ActionStamp)
#Id
private short id;
private String tla;
...
Now I want to find all Object, where 1 of the tla's of the borrowers in the last ActionStamp equals a given tla.
So far i have this:
// Select only Object with type Object.class
Query<Object> q = ds.createQuery(Object.class);
// Query the Object only that have a borrowingHistory
q.field("borrowingHistory").exists();
// Query the Object only that have borrowers in the borrowingHistory
q.field("borrowingHistory.borrowers").exists();
// This is where I'm stuck
q.field("borrowingHistory.borrowers.tla").hasThisOne(providedTla);
I get the following Error:
com.google.code.morphia.query.ValidationException: Can not use dot-notation past 'borrowers' could not be found in 'nl.technolution.loanboard.datamodel.entity.Object' while validating - borrowingHistory.borrowers.tla
How should I solve this query?
I'm parsing an XML document that has nodes like the following:
<objects>
<dog>
<data1>...</data1>
<data2>...</data2>
<data3>...</data3>
</dog>
<cat>
<data1>...</data1>
<data2>...</data2>
<data3>...</data3>
</cat>
</objects>
The elements data1, data2, data3 are always consistent. Only the parent tag varies. In my object model I have a single Object which represents all of these cases. How can I get JAXB to handle this case without knowing in advance the name of the element?
#XMLAnyElement matches all the objects but doesn't create an object of the appropriate type; I get a list of Node objects instead of my object. My object currently looks something like:
public class MyObject {
protected String otherData;
#XmlAnyElement
#XmlElementWrapper(name = "objects")
protected List<MyChildObject> childObjects;
}
public class MyChildObject {
protected String data1;
protected String data2;
protected String data3;
}
Any ideas how to handle this case short of changing the incoming XML format to use <object type="dog"> elements?
If the name is truely dynamic, then I don't think JAXB will help you these. If you have a defined number of various element names then you could use inheritance like the other post suggested. If the number of elements and names is unknown I would recommend using something like this:
#XmlMixed
#XmlAnyElement
public List<Object> getObjects() {
return objects;
}
This would bring the element is a just a DOM element. You could then use JAXB a second time to go from each of the elements into your custom type.
That would be if you had to use JAXB. You might find it easier to just use the SAX or DOM APIs directly for data like this. JAXB is really intended for well defined data that can be represented as a schema.
You can use inheritance:
#XmlRootElement(name = "dog")
public class MyDogObject extends MyChildObject {
//nothing here
}
#XmlRootElement(name = "cat")
public class MyCatObject extends MyChildObject {
//nothing here
}
This way it lets you deal with the same object type, MyChildObject, yet flexibly control the XML structure. Another benefit is that should you define specific dog/cat XML nodes in the future - they can be mapped on that corresponding subclass but not the other, as expected.