I have 2 classes:
#XmlRootElement
public class A {
private Long id;
private B b;
// setters and getters
}
and
#XmlRootElement
public class B {
private Long id;
private String field1;
private String field2;
// setters and getters
}
By default, if I transform an instance of class A to the XML, I will have all its fields (id) and the referenced B class fields (id, field1, field2) like this:
<a>
<id>2</id>
<b>
<id>5</id>
<field1>test1</field1>
<field2>test3</field2>
</b>
</a>
Is is possible to modify what fields from referenced class B are included in the XML of the A class? E.g. I want to say that when I transform an instance of A class, I just want to get id from the B class (no field1 and field2 fields), so I want to get:
<a>
<id>2</id>
<b>
<id>5</id>
</b>
</a>
I don't want to permanently annotate the B class (using #XMLTransient or #XMLElement) to achieve it, as there are cases in which I want to export whole B class as is (with id, field1 and field2.)
I just don't want to export all these fields when the B class is referenced from A.
Is this even possible with JAX-B?
You can use annotation #XmlTransient to ignore fields. Put this annotation on field itself or its getter.
You can use #XmlTransient on the field. Also the default JAXB bindings can be overridden at a global scope or on a case-by-case basis as needed by using custom binding declarations.
Check out the Guide to JAXB from Baeldung website for more examples.
Ok, I've come up with some hacky solution:
#XmlRootElement
public class A {
private Long id;
private B b;
// setters and getters
}
I've provided an additional getter just for the REST use case, so it's like:
#XMLTransient
public B getB() {
return b;
}
#XMLElement(name="b")
public Long getBForREST() {
return b.getId();
}
It results in the following structure:
<a>
<id>2</id>
<b>5</b>
</a>
It's not exactly same structure I aimed for it works for me.
I don't like this solution - an #XMLExclude({"field1", "field2"}) or something like that would be much cleaner in my opinion.
Nevertheless - for now on, it works; it's ugly, but it works.
Related
I am using #XmlRootElement annotation to get XML data from the database.
Right now, if I put #XmlTransient to getters, the fields are ignored.
For example:
public class Student {
private Integer studentId;
private String studentName;
#XmlTransient // Do not get student id
public Integer getStudentId() {
return this.studentId;
}
public String getStudentName() {
return this.studentName;
}
...// Setter goes here
Then, student ids are not appear in the XML file.
However, can I do this in the opposite way? I want to specify fields that I want to have in the XML file - there are too many fields in the Student class.
My server(Spring Framework 3.2.3) also uses the Jackson library, so I wonder I could use it if that is possible.
You could annotate your class with:
#XmlAccessorType(XmlAccessType.NONE)
Now you have to explicitly map properties in order to be serialized. See the Javadoc: http://docs.oracle.com/javaee/7/api/javax/xml/bind/annotation/XmlAccessType.html
I'm trying to use JAXB in my project and I found an issue that with Jibx was easy to handle (we stopped using it with jboss 7) but with JAXB we are having difficulties to solve.
So I have a class A as follows:
public class A
{
#XmlElement(name ="xpto")
public B fieldXPTO;
#XmlElement(name ="foo")
public B fieldFOO;
}
And my class B :
public class B
{
public String name;
public String address;
}
Now building our schema for class A we wanted to specify different names for the class B fields for each class A field. Something that when marshalling an A object would turn out like
<A>
<xpto>
<name_xpto>Peter</name_xpto>
<address_xpto>Moon Street</address_xpto>
</xpto>
<foo>
<name_foo>Ryan</name_foo>
<address_foo>Mars Street</address_foo>
</foo>
</A>
Is it possible to do this just by working with the schema ?
Thank you all,
Pedro
In my Hibernate+Spring project I've got several entities quite similar; that's why I'm using inheritance type: Table Per Class. The thing is similar to this
class CommonEntity {
private Integer id;
private String name;
private String description;
// Constructors & Setters & Getters
}
class InheritedClass1 extends CommonEntity {
private boolean active;
// Constructors & Setters & Getters
}
class InheritedClass2 extends CommonEntity {
}
As I'm using XML mapping, the mapping for the 1st inherited class contains both CommonEntity and InheritedClass1 fields/columns.
Everything's fine so far.
Here the question is, what would be the best way to implement Repositories/DAOs for the inherited entities? As they will contain common fields (for instance, probably it would end up in implementing a findByName DAO method).
My main point is to avoid implement the same findByName for all inherited class as the only difference would be the name of the Named Query (i.e. InheritedClass1_FindByName and InheritedClass2FindByName).
You could use generics to make a single DAO method that would work for any class which extends your CommonEntity like this:
public <T extends CommonEntity > T getByName(Class<T> clazz, String name) {
Criteria crit = sessionFactory.getCurrentSession().createCriteria(clazz, "named");
crit.add(Restrictions.eq("named.name", name));
return (T)crit.uniqueResult();
}
Obviously if name is not unique you would need to call crit.list() rather than uniqueResult()
I need to map some legacy XML I can't change. There are several elements that have hundreds attributes exactly the same as some other elements. The attributes all have the same name postfixed with a number. So XML might look like this:
<someElement custom1="..." custom2="..." custom78=".."/>
<anotherElmenent custom1="..." custom45="..."/>
A solution that "works" is to create a base class like so:
#XmlAccessorType(FIELD)
public class LotsaCustomIds
{
#XmlAttribute
private String custom1;
#XmlAttribute
private String custom2;
...
}
#XmlType
public class SomeElement extends LotsaCustomIds
{
....
}
But it's a shame to use inheritence here, especially since Java only has single inheritence. What I'd like to do is something like the way JPA/Hibernate do embedded objects, like:
#XmlType
public class SomeElement
{
#EmbeddedAttributes
private LotsaCustomIds customIds;
....
}
Anyway to do this?
Note: I'm the EclipseLink JAXB (MOXy) lead.
You could use MOXy's #XmlPath extension to map this use case. When you use it as #XmlPath(".") then it will pull the contents of the child object (LotsaCustomIds) into the parent object (SomeElement).
#XmlType
public class SomeElement
{
#XmlPath(".")
private LotsaCustomIds customIds;
....
}
Related Information from my Blog
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
I have successfully marshaled the following class
#XmlRootElement(name = "Field")
private static class MyField {
#XmlAttribute(name = "Name")
String name;
#XmlElement(name = "Size")
int size;
....}
Now I want to have my container class to hold multiple instances of Field, so I declared a class in the following way:
private static class MyFieldsCollection {
private Collection<MyField> fields = new LinkedList<MyField>();
public MyFieldsCollection() {}
....}
When I simply try to marshal the container field I get the following error:
class java.util.LinkedList nor any of its super class is known to this context
How do I annotate the fields member so the container class will be marshaled as a collection of fields?
You shouldn't annotate your MyField class as a #XmlRootElement as it won't be a xml root element. I think you can either annotate it with #XmlType or simply do not annotate it. You could try and put the #XmlElement tag in the getter for the "fields" attribute in your class. If it works, your XML will look like this:
<MyFieldsCollection>
<fields name="name1" size="size1"/>
<fields name="name2" size="size2"/>
</MyFieldsCollection>
If it doesn't work, and it's a shot in the dark, try changing the type of the "Collection" to "List" to check if it makes some difference. What version of Java are you using? How does the code that you use to serialize your object looks like?