Generating all fields Builder from lombok #Builder annotated class - intellij-idea

I am wondering if there is a shortcut to create full builder without manually adding fields one by one from class annotated with Builder?
Let's say we have a class:
#Builder
public class Classroom {
private Long id;
private String name;
private String location;
private String fullName;
}
It creates Classroom.builder().build(), but instead of that I want to instantly unfold a code with every field added like:
Classroom.builder()
.id()
.name()
.location()
.fullName()
.build()
Any Intellij shortcut to make that happend?

Related

Hibernate #DynamicUpdate on an immutable entity

Suppose that I have a Hibernate entity whose fields are altered via new instance creation (e.g. Lombok builder).
Does that mean that #DynamicUpdate is not going work? Is is required to change the fields via setters in this case?
P.S. Here is an example
#Table
#Entity
#Builder(toBuilder = true)
class Person {
private String firstName;
private String lastName;
}
...
Person person = personRepository.findById(1).orElseThrow();
personRepository.saveAndFlush(
person.toBuilder()
.firstName("newName")
.build() // creates new instance
);

IntelliJ: custom code generation templates

How can I define custom code generation like Getters/Setters in IntelliJ. I took a look on their docs but they don't specify where I can do this. The code I would like IntelliJ to generate for me is like below:
public class Person {
private String name;
private String username;
//I want IntelliJ to propose me to generate this after Alt+Insert
public Person withName(String name){
setName(name);
return this;
}
//and this
public Person withUsername(String username){
setUsername(username);
return this;
}
}
Thanks a lot
When you press alt+insert you can click Getter and Setter. There are Getter template and Setter template drop-downs that you can select. Click the ... and you can create new templates.
It appears you're trying to follow the builder pattern. IntelliJ already has a setter template for this called "Builder". You can select it from the setter drop-down and you should be good.

Lombok + Intellij: cannot resolve method of super class

I have a superclass
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class ErrorResponse {
#JsonProperty
private String message;
}
And I have a child one
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder(builderMethodName = "_builder") // add custom builder name to avoid compilation issue 'return type is not compatible...'
#EqualsAndHashCode(callSuper=true)
public class AskQuestionErrorResponse extends ErrorResponse {
#JsonProperty
private String status;
#Builder(builderMethodName = "_builder") // add custom builder name to avoid compilation issue 'return type is not compatible...'
private AskQuestionErrorResponse(String status, String message){
super(message);
this.status = status;
}
}
When I use a builder to create an object like this
AskQuestionErrorResponse._builder()
.status(1)
.message("my message here").build()
Intellij shows me message in red and there is an issue cannot resolve method 'message(java.lang.String)' Anyway project compiles and runs even with this error.
I've already enabled annotations precessing.
If I comment field from superclass like this
AskQuestionErrorResponse._builder()
.status(ex.getStatus().getValue()
//.message(ex.getMessage()
).build()
It works. It seems that it does not see superclass members. I've also tried maven clean and install, rebuild project.
UPDATE
Lombok plugin is installed
Annotation Processors are enabled in Preferences and in Default preferences
I found it. If you take a look to my class you'll see two #Builder annotations. I removed first one and magic happens. Now my class looks like this and there is no warning
#Data
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode(callSuper=true)
public class AskQuestionErrorResponse extends ErrorResponse {
#JsonProperty
private String status;
#Builder(builderMethodName = "_builder") // add custom builder name to avoid compilation issue 'return type is not compatible...'
public AskQuestionErrorResponse(String status, String message){
super(message);
this.status = status;
}
}
Hope it helps :)
You need to install the Intellij Lombok plugin so that it can understand the annotations before the compilation to byte code.
https://projectlombok.org/setup/intellij

JAXB serialization: Option to have a reference to inner objects

We are serializing a large number of objects. Some objects have attributes as list of objects.
I found an option in Texo serializer where such list of objects are saved as references and a lot of space is saved rather than showing same object multiple times. eg shown below:
<target:LogicalFact id="6022" version="28"
created="2014-12-01T15:53:59.000+0000"
logicalColumns="#/16651 #/10549 #/17142 #/16898 #/16542 #/16551 #/16832 #/16623 #/17230 #/16645 #/16393 #/16968 #/16575 #/17179 #/17195 #/16717 #/16636 #/16560 #/16410 #/16814 #/16610 #/16691 #/17173 #/16705 #/16838"/>
In above example, all logical columns are references. This saves space by avoiding duplicate information. Is there any such option available with JAXB serializer.
You are most probably interested in #XmlIDand #XmlIDREF which allow to reference objects.
#XmlAccessorType(XmlAccessType.FIELD)
public class Employee {
#XmlID
#XmlAttribute
private String id;
#XmlAttribute
private String name;
#XmlIDREF
private Employee manager;
#XmlIDREF
#XmlList
private List<Employee> reports;
public Employee() {
reports = new ArrayList<Employee>();
}
}
Please see this the following post by Blaise Doughan:
http://blog.bdoughan.com/2010/10/jaxb-and-shared-references-xmlid-and.html
The code snippet above is taken from this post.

how to design an interface for different object to using them in a builder design pattern?

I have at least two different classes like following :
//NOTE : these two classes have getter and setter also
class Artist {
String artistName;
String artistWebsite;
String artistDbpedia;
String artistImage;
List<String> astistAlbumsName;
List<String> astistAlbumsUrl;
}
class Venu {
String VenuName;
String VenuWebsite;
String VenuDbpdia;
String VenuImage;
String VenuDescription;
List<String> venuFans;
}
I want to have a producer class to get an xml file as an input and detect the type of xml (venu/artist) then start to create a product object based on the input.
the problem :
I want to create an interface for aggregate the similarity between above two classes so my interface would be:
interface Model {
public String getImage();
public String getName();
public String getWebsite();
public String getdbpedia();
}
Then I can implement this interface in my builder class and above two classes but how about those different methods?
such as getVenuFans / getArtistAlbumName / etc....?
How can I call them from my producer?
this is my builder :
Class Builder implements Model {
public String getImage(){}
public String getName(){}
public String getWebsite(){}
public String getdbpedia(){}
}
and this can be my producer :
Class Producer {
public Producer()
{
Builder b = null;
//assume Venu and Artist implements Model
b = (Builder) new Venu();
//I don't have access to getVenuFans()!
b = (Builder) new Artist();
//I don't have access to getArtistAlbumsName() / etc...
}
}
You don't have access to those methods because you're casting the objects to a Builder, and Builder doesn't have those methods.
I see what you're trying to do, but I don't think it will work. For example, getVenueFans (I'm assuming you mean venue) is only appropriate for the Venue class. It doesn't make sense to try and abstract that into an interface that other non-Venue classes will implement.
I think what you have is good: You've abstracted the common methods into an interface. To call the methods on Venue and Artist, the consuming code will need to cast the objects to the appropriate type, then call the methods on it. And that's not as bad as you might think. It's the consuming code that knows what type it's dealing with (otherwise, why would it be trying to call getVenueFans?), so that's the point where it makes sense to cast and call the method directly.