This question already has answers here:
Build an object from an existing one using lombok
(3 answers)
Closed 2 years ago.
Hi I'm having the following piece of code
BBResponse bbStmtResponse = BBResponse.builder().result(IN_PROGRESS).build();
After few validations, I want to update the object "bbStmtResponse" to set to other properties as
bbStmtResponse.builder().status(SUCCESS).build();
When I print the bbStmtResponse object, it doesn't hold "result" property value which was supposed to be"IN_PROGRESS". How can I overcome this, instead of using setter methods as there are more properties to set
Two ways:
Use toBuilder method
#Builder(toBuilder = true)
public BBResponse
Then use bbStmtResponse.toBuilder().status(SUCCESS)
Use #Setter to enable both builder and setter:
#Setter
#Builder(toBuilder = true)
public BBResponse
Related
Requirement
I've been asked to retrieve the value of a query annotation from a custom property stored in the application.properties file.
Prievious attempt
I tried to use #Value without success
#Repository
public interface FooRepository
extends JpaRepository<Foo, Long> {
#Value("${db.queries.distance}")
String distanceQuery; // this raises an error
#Query(nativeQuery = true, value =distanceQuery)
...
Eclipse marks "distanceQuery" and states
The blank final field distanceQuery may not have been initialized
And force me to initialize the variable as follows
public static final Double distanceQuery = null;
Unfortunately it's not what I want
Question
Is there a workaround to fix this issue?
Thank you in advance!
Instead of defining in a properties file, you can define query in a constants java file and can get value as below
#Query(nativeQuery = true, value =Constants.DISTANCE_QUERY)
Lets say I have a lombok annotated class like
#Builder
class Band {
String name;
String type;
}
I know I can do:
Band rollingStones = Band.builder().name("Rolling Stones").type("Rock Band").build();
Is there an easy way to create an object of Foo using the existing object as a template and changing one of it's properties?
Something like:
Band nirvana = Band.builder(rollingStones).name("Nirvana");
I can't find this in the lombok documentation.
You can use the toBuilder parameter to give your instances a toBuilder() method.
#Builder(toBuilder=true)
class Foo {
int x;
...
}
Foo f0 = Foo.builder().build();
Foo f1 = f0.toBuilder().x(42).build();
From the documentation:
If using #Builder to generate builders to produce instances of your own class (this is always the case unless adding #Builder to a method that doesn't return your own type), you can use #Builder(toBuilder = true) to also generate an instance method in your class called toBuilder(); it creates a new builder that starts out with all the values of this instance.
Disclaimer: I am a lombok developer.
Is there an easy way to create an object of Foo using the existing object as a template and changing one of it's properties?
(emphasis mine)
If you really want to change a single property, then there's a nicer and more efficient way:
#With
class Band {
String name;
String type;
}
Band nirvana = rollingStones.withName("Nirvana");
The wither creates no garbage, but it can change just a single field. For changing many fields, you could use
withA(a).withB(b).withC(c)....
and produce tons of garbage (all intermediate results) but than toBuilder is more efficient and more natural.
NOTE: Older versions of lombok have used #Wither annotation. See beginning of documentation.
You might also want do a copy of the object using com.fasterxml.jackson.databind.ObjectMapper
#AllArgsConstructor
#Setter
class Band {
String name;
String type;
}
ObjectMapper objectMapper = new ObjectMapper(); //it's configurable
objectMapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
objectMapper.configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false );
Band rollingStones = new Band("Rolling Stones", "Rock Band");
Band nirvana = objectMapper.convertValue( rollingStones, Band.class);
nirvana.setName("Nirvana");
it can be easily wrapped in some utility method to be used all over the project like ConvertUtils.clone(rollingStones, Band.class)
I want to configure Hibernate to set maximum length for a VARCHAR field. This maximum length is defined in a configuration file, and this configuration file is loaded by a class ValidationConfiguration.
This is my entity:
#Entity
public class MyEntity{
#Autowired /*I know this is bad practice,
I just want to let readers know that this object is instantiated.*/
private ValidationConfiguration config;
#Column(length = config.getMaxLength()) /*This gives a "java: element value
must be a constant expression"*/
String description;
//Get and set
}
Is this possible? If not, are there any workarounds?
From your code, it is clearly visible, that You are just defining the ValidationConfiguration by private ValidationConfiguration config;
But You are not Instantiating the Object.
So, Instantiate the object like new ValidationConfiguration() and since you haven't shared the code of ValidationConfiguration , i am predicting that your method is getMaxLength() not static. If the problem persists, do share the ValidationConfiguration code.
If that is a bean, then you can autowire it simply and don't create new instantiation.
I have a Questions entity which has list of options as follows:
#OneToMany(mappedBy = "question")
List<Option> options;
And in Options entity I have specified the relation as :
#ManyToOne
#JoinColumn(name="question_id")
Question question;
When I hit /api/questions , it works fine but when I hit /api/questions/1 , it gives java.lang.StackOverflowError: null
What am I doing wrong?
It's because Option refers to Question and Question to Option. You should add
#JsonIgnore to one of your class to prevent infinite linking to each other. The same thing can be with toString() method. If you use Lombok or generate default toString method, it could cause statckoverflow also. Because classs linked to class. To prevent this try to exclude link on class in one of toString method.
In Lombok in #ToString annotation add exclude statement and exclude either Option or Question. Maybe you call toString method that cases loop. #ToString(exclude = {"option"})
Now that I found how to use converters in an HTML SELECT in Spring Roo, I am trying to do the same in a list.
I managed to register a Converter in my ApplicationConversionServiceFactoryBean, but now I need to use it as well when displaying a list of my envities. I have the following entity :
#RooJavaBean
#RooToString
#RooEntity
public class Environment {
#NotNull
#Size(min = 2, max = 30)
private String name;
#ManyToOne
private Application application;
}
When displaying it as a list in the generated MVC, it looks like the application is displayed as a toString() and not using the registered converter.
What am I missing ?
You need to push-in refactor the Roo generated converter method to the application conversion factory bean.
Sometimes, by default toString() method is used for the conversion.
Alternatively, you can try pushing in and overriding the toString() method within the entity itself. You will have to remove the #RooToString annotation while doing this.
Cheers!!!