I want to use custom setter in Lombok's builder and overwrite 1 method, like this
#SuperBuilder
public class User implements Employee {
private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();
private String username;
private String password;
public static class UserBuilder {
public UserBuilder password(String password) {
this.password = ENCODER.encode(password);
return this;
}
}
}
but I have this compilation error
Existing Builder must be an abstract static inner class.
In contrast to #Builder, #SuperBuilder generates two builder classes, a public and a private one. Both are heavily loaded with generics to ensure correct type inference.
If you want to add or modify a method to the builder class, you should have a look at the uncustomized delomboked code and copy&paste the public abstract static class header from there. Otherwise you'll likely get the generics wrong, leading to compiler errors you won't be able to fix. Also have a look at the return types and statements of the generated methods to make sure you define that correctly.
The #SuperBuilder documentation also mentions this:
Due to the heavy generics usage, we strongly advice to copy the builder class definition header from the uncustomized delomboked code.
In your case, you have to customize the builder as follows:
public static abstract class UserBuilder<C extends User, B extends User.UserBuilder<C, B>> {
public B password(final int password) {
this.password = ENCODER.encode(password);
return self();
}
}
Related
I am using Lombok library in my project and I am not able to use a class annotated with #Builder in outer packages.
Is there a way to make the builder public?
MyClass instance = new MyClass.MyClassBuilder().build();
The error is:
'MyClassBuilder()' is not public in
'com.foo.MyClass.MyClassBuilder'. Cannot be accessed
from outside package
#Builder already produces public methods, it's just the constructor that's package-private. The reason is that they intend for you to use the static builder() method, which is public, instead of using the constructor directly:
Foo foo = Foo.builder()
.property("hello, world")
.build();
If you really, really, really want the constructor to be public (there seems to be some suggestion that other reflection-based libraries might require it), then Lombok will never override anything that you've already declared explicitly, so you can declare a skeleton like this with a public constructor and Lombok will fill in the rest, without changing the constructor to package-private or anything.
#Builder
public class Foo
{
private final String property;
public static class FooBuilder
{
public FooBuilder() { }
// Lombok will fill in the fields and methods
}
}
This general strategy of allowing partial implementations to override default behaviour applies to most (maybe all) other Lombok annotations too. If your class is annotated with #ToString but you already declared a toString method, it will leave yours alone.
Just to show you everything that gets generated, I wrote the following class:
#Builder
public class Foo
{
private final String property;
}
I then ran it through delombok to see everything that was generated. As you can see, everything is public:
public class Foo
{
private final String property;
#java.beans.ConstructorProperties({"property"})
Foo(final String property) {
this.property = property;
}
public static FooBuilder builder() {
return new FooBuilder();
}
public static class FooBuilder
{
private String property;
FooBuilder() { }
public FooBuilder property(final String property) {
this.property = property;
return this;
}
public Foo build() {
return new Foo(property);
}
public String toString() {
return "Foo.FooBuilder(property=" + this.property + ")";
}
}
}
The problem is you are using #Builder in the wrong way.
When Builder Pattern is used, you only need to use the static method to invoke it and then build, for example:
MyClass instance = MyClass.builder().build(); .
Please do not new the MyClassBuilder again, it breaks the encapsulation the pattern has since you are directly using the inner MyClassBuilder class. This constructor is been hided from outside, that's why you get the not accessible error. Instead it provides you the static method builder().
I have found this neat workaround:
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
#Getter
#Setter
#Builder
public class Customer {
private String id;
private String name;
public static MessageBuilder builder() {return new CustomerBuilder();}
}
The problem with this builder annotation is that, if you delombok you'll see, the generated constructor for the builder has no access indicator (public, private, protected) therefore is only visible within the same package.
This would work if the extended classes were in the same package.
I'm having the same problem and I think that lombok does not support this, for now.
I was able to find the feature request in here https://github.com/rzwitserloot/lombok/issues/1489
My suggestion is to hard implement builder pattern in this class.
as mentioned you can use the builder, now instead of user property builder() will return the instance create so you can treat as normal builder ( no need to use property)
instance = MyClass.MyClassBuilder().property1(value1).property1(value2).build();
Foo foo = Foo.builder()
.setColor(red)
.setName("Fred")
.setSize(42)
.build();
So I know there is the following "Builder" solution for creating named parameters when calling a method. Although, this only seems to work with inner static classes as the builder or am I wrong? I had a look at some tutorials for builder pattern but they seem really complex for what im trying to do. Is there any way to keep the Foo class and Builder class separate while having the benefit of named parameters like the code above?
Below a typical setup:
public class Foo {
public static class Builder {
public Foo build() {
return new Foo(this);
}
public Builder setSize(int size) {
this.size = size;
return this;
}
public Builder setColor(Color color) {
this.color = color;
return this;
}
public Builder setName(String name) {
this.name = name;
return this;
}
// you can set defaults for these here
private int size;
private Color color;
private String name;
}
public static Builder builder() {
return new Builder();
}
private Foo(Builder builder) {
size = builder.size;
color = builder.color;
name = builder.name;
}
private final int size;
private final Color color;
private final String name;
}
Use composition. To make things easier and cleaner, do not replicate all attributes in source (Foo) and builder (Builder) class.
For example, have Foo class inside Builder instead of each of Foo attribute.
simple code snippet:
import java.util.*;
class UserBasicInfo{
String nickName;
String birthDate;
String gender;
public UserBasicInfo(String name,String date,String gender){
this.nickName = name;
this.birthDate = date;
this.gender = gender;
}
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("Name:DOB:Gender:").append(nickName).append(":").append(birthDate).append(":").
append(gender);
return sb.toString();
}
}
class ContactInfo{
String eMail;
String mobileHome;
String mobileWork;
public ContactInfo(String mail, String homeNo, String mobileOff){
this.eMail = mail;
this.mobileHome = homeNo;
this.mobileWork = mobileOff;
}
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("email:mobile(H):mobile(W):").append(eMail).append(":").append(mobileHome).append(":").append(mobileWork);
return sb.toString();
}
}
class FaceBookUser {
String userName;
UserBasicInfo userInfo;
ContactInfo contactInfo;
public FaceBookUser(String uName){
this.userName = uName;
}
public void setUserBasicInfo(UserBasicInfo info){
this.userInfo = info;
}
public void setContactInfo(ContactInfo info){
this.contactInfo = info;
}
public String getUserName(){
return userName;
}
public UserBasicInfo getUserBasicInfo(){
return userInfo;
}
public ContactInfo getContactInfo(){
return contactInfo;
}
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("|User|").append(userName).append("|UserInfo|").append(userInfo).append("|ContactInfo|").append(contactInfo);
return sb.toString();
}
static class FaceBookUserBuilder{
FaceBookUser user;
public FaceBookUserBuilder(String userName){
this.user = new FaceBookUser(userName);
}
public FaceBookUserBuilder setUserBasicInfo(UserBasicInfo info){
user.setUserBasicInfo(info);
return this;
}
public FaceBookUserBuilder setContactInfo(ContactInfo info){
user.setContactInfo(info);
return this;
}
public FaceBookUser build(){
return user;
}
}
}
public class BuilderPattern{
public static void main(String args[]){
FaceBookUser fbUser1 = new FaceBookUser.FaceBookUserBuilder("Ravindra").build(); // Mandatory parameters
UserBasicInfo info = new UserBasicInfo("sunrise","25-May-1975","M");
// Build User name + Optional Basic Info
FaceBookUser fbUser2 = new FaceBookUser.FaceBookUserBuilder("Ravindra").
setUserBasicInfo(info).build();
// Build User name + Optional Basic Info + Optional Contact Info
ContactInfo cInfo = new ContactInfo("xxx#xyz.com","1111111111","2222222222");
FaceBookUser fbUser3 = new FaceBookUser.FaceBookUserBuilder("Ravindra").
setUserBasicInfo(info).
setContactInfo(cInfo).build();
System.out.println("Facebook user 1:"+fbUser1);
System.out.println("Facebook user 2:"+fbUser2);
System.out.println("Facebook user 3:"+fbUser3);
}
}
output:
Facebook user 1:|User|Ravindra|UserInfo|null|ContactInfo|null
Facebook user 2:|User|Ravindra|UserInfo|Name:DOB:Gender:sunrise:25-May-1975:M|ContactInfo|null
Facebook user 3:|User|Ravindra|UserInfo|Name:DOB:Gender:sunrise:25-May-1975:M|ContactInfo|email:mobile(H):mobile(W):xxx#xyz.com:1111111111:2222222222
Explanation:
FaceBookUser is a complex object with below attributes using composition:
String userName;
UserBasicInfo userInfo;
ContactInfo contactInfo;
FaceBookUserBuilder is a static builder class, which contains and builds FaceBookUser.
userName is only Mandatory parameter to build FaceBookUser
FaceBookUserBuilder builds FaceBookUser by setting optional parameters : UserBasicInfo and ContactInfo
This example illustrates three different FaceBookUsers with different attributes, built from Builder.
fbUser1 was built as FaceBookUser with userName attribute only
fbUser2 was built as FaceBookUser with userName and UserBasicInfo
fbUser3 was built as FaceBookUser with userName,UserBasicInfo and ContactInfo
In this example, composition has been used instead of duplicating all attributes of FaceBookUser in Builder class.
EDIT:
Group all related attributes into logical classes. Define all these classes in FaceBookUser. Instead of adding all these member variables again in Builder, contain FaceBookUser in Builder class.
For simplicity, I have added two classes: UserBasicInfo and ContactInfo . Now explode this FaceBookUser class with other attributes like
NewsFeed
Messages
Friends
Albums
Events
Games
Pages
Ads
etc.
If you duplicate all these attributes in both Builder and FaceBookUser, code will become difficult to manage. Instead, by using composition of FaceBookUser in FaceBookUserBuilder itself, you can simply construction process.
Once you add above attributes, you will build FaceBookUser in step-by-step process as usual.
It will be like this:
FaceBookUser fbUser3 = new FaceBookUser.FaceBookUserBuilder("Ravindra").
setUserBasicInfo(info).
setNewsFeed(newsFeed).
setMessages(messages).
setFriends(friends).
setAlbums(albums).
setEvents(events).
setGames(games).
setAds(ads).build();
You can sure change the fields of your Builder class to be private - then you just need a (public) getter method for each "property" on the builder; and the constructor in Foo calls those methods; instead of just fetching the fields in the Builder object.
Then you can just move your Builder class out of Foo. Simple and straightforward.
But keep in mind: in the end, Builder and Foo are very closely related. They share a common set of fields by design. So any change to Foo affects Builder; and vice versa. Thus it makes a lot of sense to keep them "close together". Maybe not as inner/outer class, but maybe still within the same source file! But then ... only one of them can be public. Is that really what you want?!
In other words: don't rip things apart just "because you can". Only do it if you have good reasons to do so, and if the thing that comes out of that is better than your current solution!
Edit: your problem might not be separation of Foo and Builder, but the fact that your Foo class has too many fields in the first place. Dont forget about the single responsibility principle ... when your class needs more than 5, 6 fields ... it is probably doing too much and should be further sliced! Keep in mind: good OO design is first of all about behavior; not about having 10, 20 fields within some object!
It's difficult to strictly define "The Builder Pattern™", and there are several degrees of freedom regarding the design choices. Some concepts can easily be mixed or abused, and beyond that, it is generally hard (and nearly always wrong) to say "you always have to do it exactly like that".
The question is what should be achieved by applying a "pattern". In your question and the example, you already mixed two concepts, namely the builder pattern and the fluent interface. Playing devil's advocate, one could even sneakily argue that the "Builder" in your case is just the Parameter Object that Thomas already mentioned, which is constructed in a special way (fluently) and enriched with some tricky combination of public and private visibilities.
Some of the possible goals of the builder pattern are overlapping or go hand in hand. But you should ask yourself what the primary goal is in your case:
Should the resulting object be immutable?
Should it be really immutable, with only final final fields, or could there also be setters that just should not be public? (The builder could still call these non-public setters!)
Is the goal to limit visibility in general?
Should there be polymorphic instantiation?
Is the main goal to summarize a large number of constructor parameters?
Is the main goal to offer an easy configuration with a fluent interface, and to manage "default" values?
...
As all these question will have an effect on the subtle differences in the design. However, regarding your actual, high level, "syntactic" question:
You could design the builder as a public static inner class (what you did in the example).
public class Person {
...
public static PersonBuilder create() { ... }
public static class PersonBuilder {
...
public Person build() { ... }
}
}
This offers the strictest form of privacy: The constructors of Person and PersonBuilder may both be private.
You could also place the actual class and its builder in separate files:
public class Person {
...
}
and
public class PersonBuilder {
...
}
A reasonable degree of privacy can be achieved here: The constructors of both can be package private (i.e. have default visibility).
In both cases, the actual usage for clients would be the same, except for the name of the builder class (package.Person.PersonBuilder vs. package.PersonBuilder). The "contents" of the classes would also be the same (except for slightly different visibilities). And in both cases, you can create subclasses of Person, if desired, depending on the builder configuration, and the builder itself can have a fluent interface.
As an alternative to the builder pattern, you could also use a parameter object:
class FooParams {
public int size;
public Color color;
public String name;
}
You can use getters and setters here, instead of public fields, if you prefer.
Then the Foo constructor takes one of these as an argument:
public Foo(FooParams params) {
this.size = params.size;
this.color = params.color;
this.name = params.name;
}
I am getting "cannot find symbol class Generated" while using the #AutoValue annotation.
public abstract class Office{
public static Office create(String cityName, String companyName, String regionName) {
return new AutoValue_Office(cityName, companyName, regionName);
}
public abstract String getCompanyName();
public abstract String getCityName();
public abstract String getRegionName();
}
Gradle dependency
compile 'com.google.auto.value:auto-value:1.0-rc1'
Also, how can add only selected properties to equals and hashcode function.
The problem is that you are using a version of Android that doesn't have the annotation javax.annotations.Generated (which was added in Java 6). You could add that manually as described in the answer to this question.
Concerning the question of excluding certain properties from equals and hashCode, there is currently no perfect way to do that. Often the desire to do this indicates a need to separate the properties that should be included into a separate class and use that in equals and hashCode. Alternatively, you could add non-final fields to the Office class and set them. For example, if regionName was not to be included, you could write something like this:
#AutoValue
public abstract class Office {
private String regionName;
public abstract String getCompanyName();
public abstract String getCityName();
public String getRegionName() {
return regionName;
}
public static Office create(String cityName, String companyName, String regionName) {
Office office = new AutoValue_Office(cityName, companyName);
office.regionName = regionName;
return office;
}
}
The main disadvantage is that regionName is not final, so you don't get the same guarantees about access to it from other threads as you do for the other properties.
I want to serialize a POJO class which is not under my control, but want to avoid serializing any of the properties which are coming from the superclass, and not from the final class. Example:
public class MyGeneratedRecord extends org.jooq.impl.UpdatableRecordImpl<...>,
example.generated.tables.interfaces.IMyGenerated {
public void setField1(...);
public Integer getField1();
public void setField2(...);
public Integer getField2();
...
}
You can guess from the example that that this class is generated by JOOQ, and inherits from a complex base class UpdatableRecordImpl which also has some bean property-like methods, which cause problems during the serialization. Also, I have several similar classes, so it would be good to avoid duplicating the same solution for all of my generated POJOs.
I have found the following possible solutions so far:
ignore the specific fields coming from superclass using mixin technique like this: How can I tell jackson to ignore a property for which I don't have control over the source code?
The problem with this is that if the base class changes (e.g., a new getAnything() method appears in it), it can break my implementation.
implement a custom serializer and handle the issue there. This seems a bit overkill to me.
as incidentally I have an interface which describes exactly the properties I want to serialize, maybe I can mixin a #JsonSerialize(as=IMyGenerated.class) annotation...? Can I use this for my purpose?
But, from pure design point of view, the best would be to be able to tell jackson that I want to serialize only the final class' properties, and ignore all the inherited ones. Is there a way to do that?
Thanks in advance.
You can register a custom Jackson annotation intropector which would ignore all the properties that come from the certain super type. Here is an example:
public class JacksonIgnoreInherited {
public static class Base {
public final String field1;
public Base(final String field1) {
this.field1 = field1;
}
}
public static class Bean extends Base {
public final String field2;
public Bean(final String field1, final String field2) {
super(field1);
this.field2 = field2;
}
}
private static class IgnoreInheritedIntrospector extends JacksonAnnotationIntrospector {
#Override
public boolean hasIgnoreMarker(final AnnotatedMember m) {
return m.getDeclaringClass() == Base.class || super.hasIgnoreMarker(m);
}
}
public static void main(String[] args) throws JsonProcessingException {
final ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(new IgnoreInheritedIntrospector());
final Bean bean = new Bean("a", "b");
System.out.println(mapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(bean));
}
}
Output:
{
"field2" : "b"
}
You can override the superclass' methods which you'd like to prevent from being output and annotate them with #JsonIgnore. The override shifts the control of property creation to the subclass while enabling its ability to filter it from the output.
For instance:
public class SomeClass {
public void setField1(...);
public Integer getField1();
public void setField2(...);
public Integer getField2();
#Override
#JsonIgnore
public String superClassField1(...){
return super.superClassField1();
};
#Override
#JsonIgnore
public String superClassField2(...){
return super.superClassField2();
};
...
}
You can use this as well instead of unnecessary overrides
#JsonIgnoreProperties({ "aFieldFromSuperClass"})
public class Child extends Base {
private String id;
private String name;
private String category;
}
The good use of inheritance is that the child classes extend or add functionality. So the usual way is to serialize the data.
A workarround would be to use a Value Object (VO) or Data Transfer Object (DTO) with the fields you need to serialize. Steps:
Create a VO class with the fields that should be serialized.
Use BeanUtils.copyProperties(target VO, source data) to copy the properties
Serialize the VO instance.
Add the following annotation in your Base Class :
#JsonInclude(Include.NON_NULL)
What tools or libraries exists for Java that will take an interface only with accessor method definitions and automatically generate an immutable object class and also a "builder" class for incrementally building new instances or changing existing instances by creating new ones?
Example input:
public interface Car {
String getModelName();
int getWheelCount();
}
Example output:
import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.NotThreadSafe;
#Immutable
public final class ImmutableCar implements Car {
#NotThreadSafe
public static final class Builder implements Car {
private String modelName;
private int wheelCount;
public Builder() {
}
public Builder(final Car car) {
modelName = car.getModelName();
wheelCount = car.getWheelCount();
}
public ImmutableCar build() {
return new ImmutableCar(wheelCount, modelName);
}
#Override
public String getModelName() {
return modelName;
}
#Override
public int getWheelCount() {
return wheelCount;
}
public void setModelName(final String modelName) {
this.modelName = modelName;
}
public void setWheelCount(final int wheelCount) {
this.wheelCount = wheelCount;
}
}
private final String modelName;
private final int wheelCount;
public ImmutableCar(final int wheelCount, final String modelName) {
this.wheelCount = wheelCount;
this.modelName = modelName;
}
#Override
public String getModelName() {
return modelName;
}
#Override
public int getWheelCount() {
return wheelCount;
}
}
Immutables (http://immutables.github.io) annotation processor is the exact match for your needs. It is full-featured and very customizable (you know all those set vs with vs no-prefix wars, - use whatever you prefer). It can generate immutable implementation with builders for interfaces, abstract classes, annotations. In addition, it can generate builders to invoke static factory methods or POJO constructors and many other things.
#Value.Immutable
public interface ValueObject {
String name();
List<Integer> counts();
Optional<String> description();
}
// Compile using annotation processor and use it like this
ValueObject valueObject =
ImmutableValueObject.builder()
.name("My value")
.addCounts(1)
.addCounts(2)
.build();
Google have a tool called AutoValue that does this, except based on an abstract base class instead of an interface.
import com.google.auto.value.AutoValue;
class Example {
#AutoValue
abstract static class Animal {
static Builder builder() {
return new AutoValue_Example_Animal.Builder();
}
abstract String name();
abstract int numberOfLegs();
#AutoValue.Builder
abstract static class Builder {
abstract Builder name(String s);
abstract Builder numberOfLegs(int n);
abstract Animal build();
}
}
}
Another similar tool is Immutables; this is probably a closer match to the question, as it uses an interface and generates an immutable implementation and a builder.
Lombok allows code like this:
#lombok.Data
#lombok.Builder
public class ImmutableCar implements Car {
private final #lombok.NonNull String modelName;
private final #lombok.NonNull int wheelCount;
}
The lombok annotations are processed at compile time (JSR-269) to generate the full class. It is also possible to look at the generated code by 'delomboking' via a Maven plugin.
check out Eclipse Model2Text project and its subprojects, especially Acceleo and Xpand. they are generally used to generate EMF-based Java code for EMF models but they can be used to generate simple POJOs too.
however this functionality does not come out of the box: you'd have to create your own code generator and templates for it. see Accelelo tutorial .
EDIT:
one more idea - one so simple that it took me a day to realize it
you can use Velocity, Freemarker or similar template library (which are normally used for html generation). though still you need to make a model somewhere, in a .txt or .xml file for example. here's a tutorial on Velocity code generation.
I just created an eclipse plugin https://github.com/karajdaar/templator.
It generates code based on Freemarker templates. The context to the Freemarker template is a ICompilationUnit which allows fully access to named classes and their information. We are using it to generate DAOs for NoSQL databases, jersey client, tests, etc.
I think it can easily do what is required here.