Suppose I have class A like this
class A {
private String Id;
private String name;
private String age;
//... some other hundres of feilds
}
How can I create another DTO named CreateA which contains all fields for A except the one I mention like id ?
something like this
#sameAs("A")
#skip("Id")
class CreateA {}
is there any java library for this ?
Related
I am trying to map object A to object B where object B sits in generated sources of the avro package. However, I do have a similar object name in src/main/java as well.
How should I tell Mapstruct to use the subs-classes of Object B to be picked up from same package where object B is?
For example
type here
//This class is source object sits in src/main/java/model
class A {
private String id;
private Name name; //this class firstName and lastName fields.
}
//this class is target object that sits in target/generated-sources/avro/*
class B {
private String id;
private Name name;
}
//this sits in target/generated-sources/avro/*
class Name {
private string firstName;
private String lastName;
}
//but I do have Class Name in src/main/java/dto as well.
How do I tell map struct to not use the Name package from src/main/java/dto but use it from target/generated-sources/avro/* ?
My Mapper abstract class looks like this:
Object B mapFromObjectA(ObjectA a); //here Object B comes from target/avro but the inner class is being picked up from dto package which is incorrect.
Is there a way, we can tell the target package directory to Map Struct?
Need some help here! I have a Java Rest API which is getting data from a .net endpoint and passing it on to the UI. The JSON properties are in capital case and I want to convert them in JAVA before sending it to the UI. Any pointers on this?
In java, I have a class like below:
public class Person {
#JsonProperty("Name")
private String name;
#JsonProperty("Age")
private int age;
}
I am using #JsonProperty as keys in .net are starting with capitalCase. How can I convert this back before sending it to the UI in Java?
Thanks for the help!
Create another class with the same structure and use there other names that you want. Something like this:
// Class to read .NET object
public class Person {
#JsonProperty("Name")
private String name;
#JsonProperty("Age")
private int age;
}
// Class to represent the object in Java REST API
public class Person {
#JsonProperty("name")
private String name;
#JsonProperty("age")
private int age;
}
// Class to represent the object in Java REST API,
// in case you use some standard library that
// uses property names for JSON as is
public class Person {
private String name;
private int age;
}
Of course you should put these classes into different packages.
Your code can look as follows:
xxx.dotnet.Person dotnetPerson = doSomethingViaDotNet(...);
yyy.rest.Person restPerson = new yyy.rest.Person();
restPerson.setName(dotnetPerson.getName());
restPerson.setAge(dotnetPerson.getAge());
...
return restPerson;
If you decide to use MapStruct, your code may looks as follows:
#Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper( PersonMapper.class );
yyy.rest.Person dotnetToRest(xxx.dotnet.Person dotnetPerson);
}
Since all attributes have the same names and types you don't need anything else in your mapper.
MapStruct will generate a class that implements this interface. Usage will be as follows:
restPerson = PersonMapper.INSTANCE.dotnetToRest(dotnetPerson);
I have a JSON response like below image, and I have made a serializable class named as Project
In the image, I have two objects (emergency_contact, and secondary_owner) inside my an array of one object. I'm trying to figure out whether what to do in order to define the object, since I want that details to be present inside my constructor.
I have done this so far:
public class Project implements Serializable {
public int id;
public String name;
public String additional_information;
//Now what to do Emergency contact
public Project(int id, String name, String additional_information){
}
}
I have thought of doing this, public EmergencyContact emergency = new EmergencyContact(param1, param2).
And make a new class named as EmergencyContact, and do a getter and setter for the params. But after doing this, I'm still confused, how would I define it my constructor?
I know I'm close, but I need some help on that.
Sure. You need to have a:
public class EmergencyContact implements Serializable {
public String name;
public String number;
public EmergencyContact(String name, String number){
// assign fields
}
}
and one for the owner:
public class EmergencyOwner implements Serializable {
public String name;
public String number;
public EmergencyOwner(String name, String number){
// assign the fields
}
}
then in your Project class you can add fields of these classes:
public class Project implements Serializable {
public int id;
public String name;
public String additional_information;
public EmergencyContact emergency_contact;
public EmergencyOwner emergency_owner;
public Project(int id, String name, String additional_information, EmergencyContact emergency_contact, EmergencyOwner emergency_owner){
// assign the fields here as well
}
}
that's it. If that's an answer to the question consider to delete this question as it is a duplicated on a 100% :)
As a note, to be correctly from the point of clean code parameters, the fields should be private in a class, and use setters / getters to set/retrieve values from/to those fields.
public class Project implements Serializable {
private int id;
private String name;
private String additional_information;
private EmergencyContact emergency_contact;
private SecondaryOwner secondary_owner;
public Project(int id, String name, String additional_information, EmergencyContact emergencyContact, SecondaryOwner secondaryOwner){
this.id = id;
this.name = name;
this.additional_information = additional_information;
this.emergency_contact = emergencyContact;
this.secondary_owner = secondaryOwner;
}
}
You will define the other two classes the same way. Now, you are probably confused about the constructor of EmergencyContact & SecondaryOwner classes.. You can device both default constructors (without parameters) and a custom one(with parameters to it, just as the one above). If you use the default constructor, make sure to set values to the fields in the object, as following :
EmergencyContact emergencyContact = new EmergencyContact();
emergencyContact.setName("the name");
emergencyContact.setNumber("a number");
then you can use this object in the constructor of Project class
I hope it was clear enough, for any other clarifications feel free to ask.
Happy coding <3
I have an entity that owns another entity:
//psuedocode
public class ClassA{
private String name;
#OneToOne
private ClassB classb;
}
public class ClassB{
private String thing1;
private String thing2;
private String thing3;
}
When I retrieve ClassA objects, I don't want to see ClassB.thing3, but I do want to see thing1 and thing 2:
{
"name":"classa",
"classb":{
"thing1":"hi",
"thing2":"there"
}
}
But if I query for ClassB I want to see everything:
{"thing1":"hi",
"thing2":"there",
"thing3":"joseph"}
So I can't just put an ignore annotation over thing3, because then I'll ignore it on the second fetch. I tried a Converter<ClassB>, but that forces me to implement toString() and fromString() for the JSON, which dies on converting the JSON object to Java-side (the converter expects a String, but gets the object instead).
I want to avoid building/parsing the JSON object myself if possible to let my json provider do the work, if possible. I'm on Johnzon.
This is possible, you need to use #NamedEntityGraph,
This should help, http://www.thoughts-on-java.org/jpa-21-entity-graph-part-1-named-entity/
Something like this should be possible by querying using SELECT NEW, but you're going to need some new Classes for that ... and won't be passing your entities directly to JSON.
new Classes:
(pseudocode)
class ResultB {
String thing1;
String thing2;
public ResultB(ClassB classB) {
this.thing1 = classB.thing1;
this.thing2 = classB.thing2;
}
}
class ResultA {
String name;
ResultB resultB;
public ResultA(ClassA classA) {
this.name=classA.name;
this.resultB=new ResultB(classA);
}
}
Query:
select new ResultA(a) from ClassA a fetch join a.classB;
Then you can pass ResultA instead of ClassA to JSON.
PS: As mentioned in the comment above, I don't think NamedEntityGraphs are the way to go here
I would always fetch all the data from the database and let the filtering to be done by the JSON provider if you want to serialize it anyway. If you use Jackson you can simply add views to your fields:
public class ClassA {
#JsonView(Views.AlwaysInclude.class)
private String name;
#JsonView(Views.AlwaysInclude.class)
#OneToOne
private ClassB classb;
}
public class ClassB {
#JsonView(Views.AlwaysInclude.class)
private String thing1;
#JsonView(Views.AlwaysInclude.class)
private String thing2;
private String thing3;
}
public class Views {
public static class AlwaysInclude {
}
}
Later when you serialize your object you just need to use your view:
String result = mapper
.writerWithView(Views.AlwaysInclude.class)
.writeValueAsString(new ClassA());
When you want to serialize only ClassB then you shouldn't use views.
String result = mapper.writeValueAsString(new ClassB());
I'm using neo4j + spring data. To access the data I'm using interfaces, that extends GraphRepository<E>. For example
public interface EntryRepository extends GraphRepository<Entry> {
#Query("start parent=node({0}), entry=node({1}) "
+ "match parent-[*1..2{removed:false}]->entry "
+ "return distinct entry")
Entry findOne(Long parentId, Long entryId);
}
I'm trying to get data, that differs from my domain models. My custom models looks like that
#QueryResult
public class EntryBean {
#ResultColumn("id")
private Long id;
#ResultColumn("name")
private String name;
#ResultColumn("content")
private String content;
...
//getters and setters
}
#QueryResult
public class BoardBean {
#ResultColumn("id")
private Long id;
#ResultColumn("name")
private String name;
...
//getters and setters
}
Obviously, that it will be better to separate duplicate fields to Base class and inherit from it. So, i'm doing next steps
#QueryResult
public class BaseBean {
#ResultColumn("id")
private Long id;
#ResultColumn("name")
private String name;
...
}
#QueryResult
public class EntryBean extends BaseBean{
#ResultColumn("content")
private String content;
...
//getters and setters
}
And I don't need BoardBean anymore. But when I'm trying run query
public interface EntryRepository extends GraphRepository<Entry> {
#Query("start user=node({0}), board=node({1}) "
+ "... "
+ "return id(entry) as id, entry.name as name, entry.content as content")
List<EntryBean> getRelatedEntries(Long userId, Long boardId);
}
I get filled by data just fields that directly declared into EntryBean class (i. e. "content" field).
So, How I can correctly implement the #QueryResult class hierarcy?
This is a bug which has been present for almost two years (even in 2.3.5.RELEASE!) in the class in charge of converting annotated POJOs.
Indeed, it calls getDeclaredFields on the most concrete type thus skipping possibly inherited annotated fields.
Before the issue is fixed, my piece of advice would be to tolerate this superficial field duplication on your side and not relying on inheritance for now.