Marshalling an object that has object fields - java

Not sure if the title makes any sense.
I have an object that I want to marshal using JAXB that looks like this:
#XmlRootElement(name = "subscriptionRequest")
public class RegistrationRequest {
private Long id;
private RegistrationSource registrationSource;
}
The RegistrationSource object:
public class RegistrationSource {
private Integer id;
private String code;
}
I want to create an xml that has the following layout:
<subscriptionRequest registrationSource="0002">
...
</subscriptionRequest>
where the registrationSource attribute value is the code field value from the RegistrationSource object.
What xml annotations do I need to use?

#XmlAttribute on registrationSource, #XmlValue on code. Note that in this case you also should have #XmlTransient on other fields of RegistrationSource, such as id
EDIT: This works:
#XmlRootElement(name = "subscriptionRequest")
public class RegistrationRequest {
private Long id;
private RegistrationSource registrationSource;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
#XmlAttribute
public RegistrationSource getRegistrationSource() { return registrationSource; }
public void setRegistrationSource(RegistrationSource registrationSource)
{
this.registrationSource = registrationSource;
}
}
-
public class RegistrationSource {
private Integer id;
private String code;
#XmlTransient
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
#XmlValue
public String getCode() { return code; }
public void setCode(String code) { this.code = code; }
}

If you want to generate this class automatically using some tools , then try this -
Generate xsd from your xml using tools like Trang, and then generate java file from xsd using jaxb. Life would be much simpler :)

The lame approach would be to add something like
#XmlAttribute(name = "registrationSource")
private String getCode() {
return registrationSource.code;
}
to your RegistrationSource -- but there must be a more elegant way...

Related

Mapstruct case insensitive mapping

is there a way in mapstruct to ignore the case of the fields when mapping. let say i want to map following two classes
public class Customer {
private String ID;
public String getID() {
return ID;
}
public void setID(String iD) {
this.ID = iD;
}
}
public class CustomerDetails {
private String id;
public String getId() {
return ID;
}
public void setId(String id) {
this.id = id;
}
}
MapStruct is not automatically mapping the fields because getter methods names that doesn't match. Is there a way to configure MapStruct to ignore the case of the fields and map them automatically
A custom AccessorNamingStrategy can be implemented that would lowercase the element name and thus making it case insensitive.
e.g.
public class CaseInsensitiveAccessorNamingStrategy extends DefaultAccessorNamingStrategy {
#Override
public String getPropertyName(ExecutableElement getterOrSetterMethod) {
return super.getPropertyName( getterOrSetterMethod ).toLowerCase( Locale.ROOT );
}
#Override
public String getElementName(ExecutableElement adderMethod) {
return super.getElementName( adderMethod ).toLowerCase( Locale.ROOT );
}
}
Not sure if you can configure mapstruct to map case insensitive but you always can define what should be mapped like this:
#Mapping(source = "ID", target = "id")
CustomerDetails toCustomerDetails(Customer customer);

How to select fields in spring data?

I have entity as follow.
#Entity
#Table(name = "BankProduct")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
#ManyToOne
private ProductUseType type;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#ManyToOne
private ProductSerial serial;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ProductUseType getType() {
return type;
}
public void setType(ProductUseType type) {
this.type = type;
}
public ProductSerial getSerial() {
return serial;
}
public void setSerial(ProductSerial serial) {
this.serial = serial;
}
}
My controller is :
#RestController
public class DEmoController {
#Autowired
private ProductRepository productRepository;
#GetMapping("/products")
public Returns products() {
return new Returns(ReturnStatus.SUCCESS.getStatus(), productRepository.findAll(), null);
}
}
It will load both of type and serial of product.
Can I only load type but not to load serial?
I don't want to add fetch=FetchType.LAZY to serial, because if next time I want to load serial but not to load type, it will be terrible.
Check the Projection interface
Create a interface ProductProjection
interface ProductProjection {
String getName();
String getType();
}
and add a method in you Repository
List<ProductProjection> findAllProjection()
That's the whole point of fetch=FetchType.LAZY. It'll not load any of your types/fields until you ask for them explicitly.
Take a look at this question: Link

How can I generate both standard accessors and fluent accessors with lombok?

I tried this.
#lombok.Getter
#lombok.Setter
#lombok.Accessors(chain = true, fluent = true)
private String prop;
And #Accessor took precedence and getProp and setProp are not generated.
How can I make it generate this?
public String getProp() {
return prop;
}
public String prop() {
//return prop;
return getProp(); // wow factor
}
public void setProp(String prop) {
this.prop = prop;
}
public Some prop(String prop) {
//this.prop = prop;
setProp(prop); // wow factor, again
return this;
}
Unfortunately this is impossible. You need to implement own getters and setters, and add #Getter #Setter and #Accessors(fluent = true) annotaions to achieve this.
#Getter
#Setter
#Accessors(fluent = true)
public class SampleClass {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
In result you will have class like:
public class SampleClass {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int id(){
return id;
}
public SampleClass id(int id){
this.id=id;
return this;
}
}
I'm afraid you can't.
From the doc (emphasis is mine):
The #Accessors annotation is used to configure how lombok generates and looks for getters and setters.
So #Accessors doesn't generate anything, it's just a way to configure #Getter and #Setter.
If you really want fluent and regular getter/setter, you can add (manually) the regular one and make them delegate to the fluent ones.
#Accessors(chain = true)
#Setter #Getter
public class Person {
private String firstName;
private String lastName;
private int height;
}
....
#Test
public void testAccessors() {
Person person = new Person();
person.setFirstName("Jack")
.setLastName("Bauer")
.setHeight(100);
assertEquals("Jack", person.getFirstName());
assertEquals("Bauer", person.getLastName());
assertEquals(100, person.getHeight());
}

Hibernate Field Annotaion Behaviour

Please help me to understand why hibernate field based annotation works based on the primarykey field?.
Model Class 1 takes docnum field value from getter and Model Class 2 too.Inspite of both places only docnum is annotated based on the getter only.It works based on id field which is having annotaion in field of Model Class 2 and in Model Class 1 based on getter.
Model Class 1:
#Entity(name="RDT_ORDER")
public class Order {
private int id;
private String docnum;
#Id
#Column(name="ORDID")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column(name="ORD_DOCNUM")
public String getDocnum() {
return docnum+" getter";
}
public void setDocnum(String docnum) {
this.docnum = docnum;
}
}
Model Class 2:
#Entity(name="RDT_ORDER")
public class Order {
private int id;
private String docnum;
#Id
#Column(name="ORDID")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column(name="ORD_DOCNUM")
public String getDocnum() {
return docnum+" getter";
}
public void setDocnum(String docnum) {
this.docnum = docnum;
}
}
Output :table(RDT_ORDER) values
ID DOCNUM
5 docnum5
6 docnum6 getter

Map one object structure to an different XML structure

I have an object similar to the following:
public class FooObj
{
private Long id;
private List<BarObj> subBar;
private String someStr;
public Long getId()
{
return id;
}
public List<BarObj> getSubBar()
{
return subBar;
}
public String getSomeStr()
{
return someStr;
}
public void setId(Long id)
{
this.id = id;
}
public void setSubBar(List<BarObj> subBar)
{
this.subBar = subBar;
}
public void setSomeStr(String someStr)
{
this.someStr = someStr;
}
public static class BarObj
{
private String groupId;
private Long id;
public String getGroupId()
{
return groupId;
}
public Long getId()
{
return id;
}
public void setGroupId(String groupId)
{
this.groupId = groupId;
}
public void setId(Long id)
{
this.id = id;
}
}
}
And I want to map the Object to an XML structure like the XML in the link: http://pastebin.com/cw018jqc EDIT:(Please look at the ObjBars element for an exact definition of what I'm looking for.)
Is there any library available that would allow me to do this?
So you're basically trying to split a list into multiple sublists before you serialize it to XML? I think that JAXB could really help you here. I think you could use an #XmlTypeAdapter to convert between List<BarObj> and List<List<BarObj>>, which would be one way of representing this data the way you want it marshalled to XML. Check out http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html for details.

Categories

Resources