java error : constructor is already defined in class - using lombok - java

The error
java: constructor Restaurant() is already defined in class
com.example.order_system.domain.Restaurant
appear when I add this class and run the program
#Entity
#NoArgsConstructor
#RequiredArgsConstructor
#Getter
#Setter
#ToString
public class Restaurant {
#Id
#GeneratedValue
private long id;
#NotEmpty(message = "The restaurant must have a name")
private String name;
#NotEmpty(message = "Please add a description for this restaurant")
private String description;
#NotEmpty(message = "The restaurant must have a location")
private String location;
#OneToMany(mappedBy = "restaurant", fetch = FetchType.EAGER)
private List<ContactDetails> contactDetails = new ArrayList<>();
}

As mentioned in documentation #RequiredArgsConstructor is built using final fields:
#RequiredArgsConstructor generates a constructor with 1 parameter for
each field that requires special handling. All non-initialized final
fields get a parameter, as well as any fields that are marked as
#NonNull that aren't initialized where they are declared. For those
fields marked with #NonNull, an explicit null check is also generated.
The constructor will throw a NullPointerException if any of the
parameters intended for the fields marked with #NonNull contain null.
The order of the parameters match the order in which the fields appear
in your class.
So either remove #RequiredArgsConstructor annotation or mark some of fields with final keyword (or #NonNull annotation).

Try to change #RequiredArgsConstructor to #AllArgsConstructor and that's been fine.
See more in documentation

Related

How do I use lombok #Builder to store different values?

I have the following JPA entity
#Data
#Builder
public class Post {
#Id
#GeneratedValue
UUID id;
#OneToMany
Set<PostTags> tags;
String content;
}
#Data
public class PostTag {
#Id
#GeneratedValue
UUID id;
#OneToOne
Post post;
String tag;
}
Using lombok #Builder I want to be able to do the following
Post post = Post.builder()
.tags("hello", "world")
.content("Hello world")
.build();
I am presuming I need a custom builder along the lines of
public static class PostBuilder {
private Set<String> myTags = new HashSet<>();
public PostBuilder tags(String... tags) {
myTags.addAll(Arrays.asList(tags));
return this;
}
}
From the documentation it appears there ObtainVia annotation that I can use, but I am not sure how to get around it (no example on the doc) and especially since I only want myTags to be a builder specific thing, and not be exposed on the main class itself.
ObtainVia only works for toBuilder, so that won't help much in this case.
I suggest the following approach.
First, add a factory method in PostTag, e.g. createTag(String). This method only sets tag in the instance it creates and leaves everything else null. Statically import it into the class where you want to use PostBuilder.
Next, use #Singular on tags. Then you can write:
Post post = Post.builder()
.tag(createTag("hello"))
.tag(createTag("world"))
.content("Hello world")
.build();
Finally, customize the build() method so that it first creates the Post instance (like an uncustomized build() method would) and then sets this newly created Post instance as post in all PostTag instances.
Have a look at the delomboked code to make sure you use the right builder class and method headers when customizing the builder.
You can use #Accessors for what you're asking:
Post
#Data
#Accessors(chain = true)
public class Post {
#Id
#GeneratedValue
private UUID id;
#OneToMany
private Set<PostTags> tags;
private String content;
public Post tags(String... tags) {
Arrays.stream(tags)
.map(tag -> PostTags.builder().tag(tag).build())
.forEach(this.tags::add);
return this;
}
}
PostTags
#Data
#Builder
public class PostTags {
#Id
#GeneratedValue
private UUID id;
#OneToOne
private Post post;
private String tag;
}
When you using #Accessors(chain = true), The setters will return this reference instead of void, and then your code will act this way:
Post post = new Post().setId(id).tags("aaa", "bbb");
If you want your code to be more similar to builder then add fluent value to the annotation: #Accessors(chain = true, fluent = true)
It will remove the set<Something> from the setters and just use the name of the fields, and then your code will look like this:
Post post = new Post().id(id).content("hello").tags("aaa", "bbb");

#BasePathAwareController Exception: could not initialize proxy - no Session

#BasePathAwareController
public class MetricController {
#Autowired
private MetricRepository metricRepository;
#Transactional
#RequestMapping(method = RequestMethod.GET, value = "/metrics/in/{id}")
public #ResponseBody
MetricDTO getMetric(#PathVariable Long id) {
return MetricDTO.fromEntity(metricRepository.getOne(id));
}
}
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(
uniqueConstraints = #UniqueConstraint(columnNames = {"metricType", "instanceType"}, name = "customUniqueId")
)
public class Metric implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true)
private String name;
private SourceType sourceType;
private String metricTypeField;
private String metricType;
private String instanceType;
private String instanceTypeField;
#ElementCollection
private List<String> metricIdFields;
#ElementCollection
private List<String> valueFields;
#ElementCollection
private Map<String, String> virtualFieldValueEx;
}
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
public class MetricDTO {
private SourceType sourceType;
private String metricTypeField;
private String metricType;
private String instanceType;
private String instanceTypeField;
private List<String> metricIdFields;
private List<String> valueFields;
private Map<String, String> virtualFieldValueEx;
public static MetricDTO fromEntity(Metric metric) {
return new MetricDTO(
metric.getSourceType(),
metric.getMetricTypeField(),
metric.getMetricType(),
metric.getInstanceType(),
metric.getInstanceTypeField(),
metric.getMetricIdFields(),
metric.getValueFields(),
metric.getVirtualFieldValueEx()
);
}
}
Since #RepositoryRestController in Spring Data Rest is not compatible with Swagger, I changed it to #BasePathAwareController.
So, the problem is that the controller is not working properly.
The error history is as follows.
Could not write JSON: failed to lazily initialize a collection of role: com.jmsight.management.entity.Metric.metricIdFields, could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.jmsight.management.entity.Metric.metricIdFields, could not initialize proxy - no Session (through reference chain: com.jmsight.management.dto.MetricDTO["metricIdFields"])
Using #RepositoryRestController works normally.
What is the problem? Is it resolvable?
If you check the source of #BasePathAwareController then you can see that it's not annotated with #Controller.
So if a class is annotated only with #BasePathAwareController then it won't be picked neither by the default SpringMvc neither RepositoryRestMvc.
The former picks classes annotated with #Controller or #RequestMapping, the latter picks only classes annotated with #RepositoryRestController.
So once again, just to make it clear: #BasePathAwareController is NOT an 'extension' of #Controller, it's just a additional 'sign' annotation.
You can use #Controller together with #BasePathAwareController instead of #RequestMapping too.
I believe it's a misleading naming, or simply a bug in the implementation.
One more thing.
If you switch the from #RepositoryRestController to #Controller/#RequestMapping, then your controller will be handled a completely different way.
It could look that it works the same way, but it's called by a completely different handlerMapping: which uses different converters, argumentResolvers, even a different objectMapper.
There could be unpleasant surprises if you need to implement more complicated handler-methods in your controller-class.
I solved it.
To share, #BasePathAwareController should be written in class as #RequestMapping.
I don't know why. If you know reason teach me please.
#BasePathAwareController
#RequestMapping(value = "your url value")
public class MetricController {}

How to get field value from jpa Entity annotate with lombook annotations?

I have Entity class annotated with lombook annotation (https://projectlombok.org/features/all):
#Getter
#Setter
#EqualsAndHashCode
#ToString
#RequiredArgsConstructor
#NoArgsConstructor
#AllArgsConstructor
#Builder
#Entity
#Table(name = "members")
public class Member implements Serializable {
private final static long serialVersionUID= 1l;
#id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id", unique = true)
private Long id;
#Column(name="name")
#NonNull
private String name;
#Column(name="photo")
#NonNull
private String photo;
#Column(name="descriotion")
private String descriotion;
#Column(name="winner_in_period")
private String winnerInPeriod;
#Column(name="created_date")
private Date createdDate;
#Column(name="deleted")
private Boolean deleted;
}
And I have service which gives me data from the database using this Entity.
Finally I try to get some data from Member object
List<Member> lastMembers = memberService.getMembers(0, lastMembersCount);
if(lastMembers != null)
lastMembers.forEach(member -> {
System.out.println(member.[IN THIS PLACE I DONT HAWE ANY GETTERS for table field]);
});
But I don't have any getters in Member object. When I write member.getName() I have error(IDEA suggested me to create getter 'getName()').
How to use lombook with jpa entity?
How to access to field which was marked with lombok annotations like #Getter or #Setter?
If you want to use 'lombok' you should install IDEA plugin and restart IDEA. After this simple steps, all will work nicely. Lombok is amazing
Enable "annotation processing".
Build, Execution, Deployment -> Compiler -> Annotation Processor: Enable annotation processing

Excluding ID attribute of base entity in the sub-entity in Hibernate

Lets assume we have the following situation:
We want to inherit all the values of the class Articles except one it's name for instance. How can we achieve it? I know that if we want to inherit everything from the Articles just write
public class Fruits extends Articles{ ... }
but how can we manage to inherit only specific attributes of the class Articles, ie. every attribute except one and one attribute leave intact?
EDIT:
#Entity
#Table(name = "Article")
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Article {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
#Basic(optional = false)
#Column(name = "ART_ID")
private Long id;
#Basic(optional = false)
#Column(name = "ART_NAME")
private String name;
#Basic(optional = true)
#Column(name = "ART_COST")
private String cost;
// ...
}
#Entity
#Table(name="Fruits")
#AttributeOverrides({
#AttributeOverride(name="name", column=#Column(name="ART_NAME")),
#AttributeOverride(name="cost", column=#Column(name="ART_COST")),
})
// This is what is causing the issue. Fruits inherits something which is already defined in it's scope, and as the result can't declare exactly how to process it.
public class Fruits extends Article {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
#Basic(optional = false)
#Column(name = "FRU_ID")
private Long fruitID;
#Column(name="FRU_FROZEN")
private String fruFrozen;
//...
}
So, I think code won't work, because this will result in multiple IDs in the entity hierarchy, so is there any other way I can solve this?
You can't remove a member from Articles
When name is a member of Articles and Fruits IS A Articles,
there could not be a way to remove name
You may hide some members from Articles using scope private
An other approach is to create a class "BaseArticles" without the member name.
Then derive both Articles AND Fruits from BaseArticles
public BaseArticles {
// HAS NO private String name;
...
}
public Article extends BaseArticles {
private String name;
...
}
public Fruits extends BaseArticles {
// WITHOUT private String name;
...
}
However, it is not simple but possible to deal with OO-inheritance using hibernate.
There is an annotation but I do not know off hands
You can put base class not required attribute as a private.

Explicit constructor using Lombok?

I'm rewriting some messy code that manages a database, and saw that the original programmer created a class mapped to the database like so:
(I've removed unnecessary code that has no purpose in this question)
#Entity
#Data
#EqualsAndHashCode(callSuper = false, of = { "accessionCode", "header", "date" })
#SuppressWarnings("PMD.UnusedPrivateField")
public class PDBEntry implements Serializable {
#Id
#NaturalId
#NotEmpty
#Length(max = 4)
private String accessionCode;
#NaturalId
#NotEmpty
private Date date;
#NaturalId
// We allow for the header to be 'null'
private String header;
private Boolean isValidDssp;
#Temporal(TemporalType.TIMESTAMP)
private Date lastUpdated = new Date(System.currentTimeMillis());
protected PDBEntry(){}
public PDBEntry(String accessionCode, String header, Date date){
this.accessionCode = accessionCode;
this.header = header;
this.date = date;
}
}
I am still a beginner at Hibernate and using Lombok, but wouldn't this do the same thing and wouldn't Lombok automatically create the needed constructor for you?
#Entity
#Data
#SuppressWarnings("PMD.UnusedPrivateField")
public class PDBEntry implements Serializable {
#Id
#NaturalId
#NotEmpty
#NonNull
#Length(max = 4)
private String accessionCode;
#NaturalId
#NotEmpty
#NonNull
private Date date;
#NaturalId
// We allow for the header to be 'null'
private String header;
private Boolean isValidDssp;
#Temporal(TemporalType.TIMESTAMP)
private Date lastUpdated = new Date(System.currentTimeMillis());
}
Also, the original programmer of this code says he allows for the header to be 'null', yet he explicitly created a constructor that needs a value for header. Am I missing something or is this a bit contradictory?
Have a look at #NoArgsConstructor, #RequiredArgsConstructor, #AllArgsConstructor.
The constructor behavior of #Data is like #RequiredArgsConstructor:
#RequiredArgsConstructor generates a
constructor with 1 parameter for each
field that requires special handling.
All final fields get a parameter, as
well as any fields that are marked as
#NonNull that aren't initialized where
they are declared.
Given that none of your fields are either final or #NonNull, this will result in a no-argument constructor. However, this is not the most expressive way to achieve this behavior.
What you'll probably want in this case is a #NoArgsConstructor (optionally combined with a #AllArgsConstructor), to clearly communicate the intended behavior, as is also indicated in the documentation:
Certain java constructs, such as
hibernate and the Service Provider
Interface require a no-args
constructor. This annotation is useful
primarily in combination with either
#Data or one of the other constructor
generating annotations.
That bit is contradictory you're right. I've not used Lombok before but with hibernate if you want to be able to create a bean and persist you need the default constructor as given above as far I was aware. It uses Constructor.newInstance() to instantiate new objects.
Here is some hibernate documentation which goes into more detail.
Hibernate Documentation
If you are using #Data with a #NonNull field and still want a noargs-constructor, you might wanna try to add all 3 annotation together
#NoArgsConstructor
#RequiredArgsConstructor
#AllArgsConstructor
Apparently an old intelliJ bug which I did replicate in Eclipse Kepler and lombok v0.11.4
#NoArgsConstructor,
#RequiredArgsConstructor,
#AllArgsConstructor
Generate constructors that take no arguments, one argument per final / non-null field, or one argument for every field. Read this lombok-project
#Data
#RequiredArgsConstructor /*Duplicate method Someclass() in type Someclass*/
#NoArgsConstructor(access=AccessLevel.PRIVATE, force=true) /*Duplicate method Someclass() in type Someclass*/
#Entity
public class Someclass {
#Id
private String id;
private String name;
private Type type;
public static enum Type { X , Y, Z}
}
Fixed it by making member variables final
#Data
#RequiredArgsConstructor
#NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
#Entity
public class Someclass {
#Id
private final String id;
private final String name;
private final Type type;
public static enum Type { X , Y, Z}
}

Categories

Resources