I am new to Spring Boot framework and lombok.
I defined my entity like that:
#Entity
#Table(name = "student")
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
public class Student implements Serializable{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String firstName;
private String lastName;
private String email;
}
I also create a controller where I add the following:
#PostMapping(path="/add") // Map ONLY POST Requests
public #ResponseBody String addNewUser (#RequestParam String name
, #RequestParam String email) {
// #ResponseBody means the returned String is the response, not a view name
// #RequestParam means it is a parameter from the GET or POST request
Student st = new Student();
st.setFirstName(name);
st.setEmail(email);
//studentservice.save(st);
return "Saved";
}
I dont know why I have a red line under setFirstName. They ask me to create this function in the student class.
I am using eclipse.
please follow the steps as below:
check pom.xml for lombok dependency
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
Now you can check your IDE,
I hope, it helps!
Related
I need a custom validator in Spring Boot(version 2.7.x). My User class is defined as:
class User{
private String email;
private String phone;
private String name;
private String address;
private String city;
private String country;
private String postalCode;
//getters and setters
}
I'm trying to validate the following requirements:
Either phone or email or a combination of (name+address+city+country+postalCode) is mandatory
If (name+address+city+country+postalCode) is present, they should be not null.
Please help with your suggestions as to how do I go about in implementing it.
you can use JSR-303 valiation implementation that hibernate-validator
and it is conventient to use annotation for valiate which
is in package javax.validation.constraints
here is code sample that
you can use #NotNull annotation above Field that mark the field should be not null
entity
class User{
private String email;
private String phone;
private String name;
#NotNull(message = "address should be not null")
private String address;
private String city;
private String country;
private String postalCode;
//getters and setters
}
validatorUtil
#Slf4j
public class ValidatorUtil {
static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public static <T> Set<ConstraintViolation<T>> validateOne(T t , Class<?>... group) {
Set<ConstraintViolation<T>> validateResult = validator.validate(t,group);
return validateResult;
}
}
valiatorTest
#Slf4j
public class ValiatorTest {
#Test
public void vailator(){
User accountInfo = new User();
Set<ConstraintViolation<User>> constraintViolations = ValidatorUtil.validateOne(accountInfo);
Assertions.assertTrue(CollectionUtil.isNotEmpty(constraintViolations));
}
}
if you build project with maven ,add hibernate-validator dependency to pom
<properties>
<hibernate.validator.version>6.0.14.Final</hibernate.validator.version>
</properties>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate.validator.version}</version>
</dependency>
if you want learn more , please accroding to this article Which #NotNull Java annotation should I use?!
i am trying to use quarkus reactive with vert.x and hibernate reactive.
this is my pom.xml:
<quarkus-plugin.version>1.12.2.Final</quarkus-plugin.version>
and
<quarkus.platform.version>1.12.2.Final</quarkus.platform.version>
with:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-mysql-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-web</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-reactive</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
this is my application.properties file:
# postgres-configuration
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=partner_usr
quarkus.datasource.password=postgrespw
quarkus.datasource.reactive.url=vertx-reactive:postgres://localhost:3310/partnerdb
# test, but not working (schema's won't created)
quarkus.hibernate-orm.database.generation.create-schemas=true
# working (drop-and-create only on mysql, not on postgres)
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=true
quarkus.http.cors=true
Then, i have following entities:
#Data
#MappedSuperclass
public abstract class IdEntity {
#Id
#SequenceGenerator(name = "entitySeq", sequenceName = "entitiy_id", allocationSize = 1, initialValue = 5)
#GeneratedValue(generator = "entitySeq", strategy = GenerationType.AUTO)
private Long id;
}
#Data
#Entity
#EqualsAndHashCode(callSuper = true)
public class Person extends IdEntity {
private String firstName;
private String lastName;
public Person() {
}
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Address personAddress;
}
#Data
#Entity
#EqualsAndHashCode(callSuper = true)
public class Address extends IdEntity {
private String street;
private String houseNumber;
private int postalCode;
private String city;
#OneToMany(orphanRemoval = true, mappedBy = "personAddress", fetch = FetchType.LAZY)
private List<Person> persons = new ArrayList<>();
public Address() {
}
}
Now, i am calling a reactive web-service with a reactive db access:
#Path("/person")
#ApplicationScoped
public class PersonResource {
#Inject
io.vertx.mutiny.pgclient.PgPool sqlClient;
#Inject
Mutiny.Session mutinySession;
#GET
//#Produces(MediaType.APPLICATION_JSON)
#Path("/list-persons")
#Route(path = "/list-persons", methods = HttpMethod.GET, produces = MediaType.APPLICATION_JSON)
#Transactional
public Multi<Person> listAllPersons() {
// return sqlClient.query("SELECT * FROM Person ORDER BY lastName ASC").execute()
// .onItem().transformToMulti(set -> Multi.createFrom().iterable(set))
// .onItem().transform(this::transformPersons);
return mutinySession.createQuery("SELECT f FROM Person f ORDER BY f.lastName")
.getResults().onItem().transform(this::transformObject);
}
private Person transformObject(Object f) {
return (Person)f;
}
private List<Object> transformPersons(Object f) {
final Person person = (PartnerMockEntity)f;
final List<Object> bogus = new ArrayList<>();
bogus.add(partner);
return bogus;
}
}
Exception:
Resulted in: com.fasterxml.jackson.databind.JsonMappingException: Cannot store to object array because "this.loadedState" is null (through reference chain: de.subito.model.Person["personAddress"]->de.subito.model.Address["person"])
I tried to use :
FetchType.EAGER on Address in Person
I removed the #OneToMany Relation in Address: this solves the error (yay), but the addresses won't be returned in the resulting json (id is existing, but the values are not fetched)
The questions is, how can i fetch in reactive those kind of relations without getting errors?
Or do i need a angular page in order to display this correctly?
Somehow i forgot about how fetchType.Lazy works.
Simply add a join fetch into the hql and everything works as expected.
SELECT p from Person p left join fetch p.personAddress
When using this query, there's no session/closed or any other exception thrown and the json result will be displayed as expected.
Additional note: in order to avoid recursive serialization, it is required to use the
#JsonManagedReference and #JsonBackReference
Annotations, depending on your needs to your relations.
I have a super Entity class like this:
#Getter
#Setter
#NoArgsConstructor
public class GenericEntity {
#Id
private Long id;
#JsonIgnore
#CreatedBy
private Long createdBy;
#JsonIgnore
#CreatedDate
private Long createdDate;
#JsonIgnore
#LastModifiedBy
private Long updatedBy;
#JsonIgnore
#LastModifiedDate
private Long updatedDate;
#JsonIgnore
#Version
private Integer version = 0;
}
and a Role class extends from GenericEntity like this:
#Getter
#Setter
#NoArgsConstructor
public class Role extends GenericEntity {
private String name;
private String desc;
private Integer sort;
}
And after that I have interface RoleRepo like this:
#Repository
public interface RoleRepo extends ReactiveCrudRepository<Role, Long>;
In Router function, I have 2 handler methods
private Mono<ServerResponse> findAllHandler(ServerRequest request) {
return ok()
.contentType(MediaType.APPLICATION_JSON)
.body(roleRepo.findAll(), Role.class);
}
private Mono<ServerResponse> saveOrUpdateHandler(ServerRequest request) {
return ok()
.contentType(MediaType.APPLICATION_JSON_UTF8)
.body(request.bodyToMono(Role.class).flatMap(role -> {
return roleRepo.save(role);
}), Role.class);
}
The method findAllHandler works fine, but the saveOrUpdateHandler throw exception like this:
java.lang.IllegalStateException: Required identifier property not found for class org.sky.entity.system.Role!
at org.springframework.data.mapping.PersistentEntity.getRequiredIdProperty(PersistentEntity.java:105) ~[spring-data-commons-2.2.0.M2.jar:2.2.0.M2]
at org.springframework.data.r2dbc.function.convert.MappingR2dbcConverter.lambda$populateIdIfNecessary$0(MappingR2dbcConverter.java:85) ~[spring-data-r2dbc-1.0.0.M1.jar:1.0.0.M1]
But when I move
#Id
private Long id;
from GenericEntity class to Role class, the two methods work fine.
Are there any Annations #MappedSuperclass/JPA in Spring Reactive Data like that
I wish the id field in GenericEntity for all extends class
Thanks for your help
Sorry, my English so bad
I had a similar problem and after some search, I didn't find an answer to your question, so I test it by writing code and the answer is spring data R2DBC doesn't need #Mappedsuperclass. it aggregates Role class properties with Generic class properties and then inserts all into the role table without the need to use any annotation.
In my controller I have annotated the request parameter with the #Valid annotation and the field of my DTO with the #NotNull annotation, but the validation doesn't seem to work.
Are there any configurations to do in order to proceed with the validation? Following there are the Controller and the DTO class details.
#RepositoryRestController
#RequestMapping(value = "/download_pdf")
public class PurchaseController {
#Autowired
private IPurchaseService iPurchaseService;
#Loggable
#RequestMapping(value = "view_order", method = RequestMethod.POST)
public ResponseEntity getPDF(#RequestBody #Valid CustomerOfferDto offer,
HttpServletResponse response) {
return iPurchaseService.purchase(offer, response);
}
}
public class CustomerOfferDto {
#NotNull
private String agentCode;
// getter and setter...
}
Following are the steps I did to make it work.
Add dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Constraints in DTO class:
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#ValidTaskDTO
public class TaskDTO {
#FutureOrPresent
#NotNull(message = "DueDate must not be null")
private ZonedDateTime dueDate;
#NotBlank(message = "Title cannot be null or blank")
private String title;
private String description;
#NotNull
private RecurrenceType recurrenceType;
#Future
#NotNull(message = "RepeatUntil date must not be null")
private ZonedDateTime repeatUntil;
}
RestController method with #Valid annotation on requestBody argument:
#RestController
#RequestMapping("/tasks")
#Validated
public class TaskController {
#PostMapping
public TaskDTO createTask(#Valid #RequestBody TaskDTO taskDTO) {
.....
}
}
On making a POST request with requestbody containing null value for dueDate, I got the expected error message as shown below.
{
"timestamp": "2021-01-20T11:38:53.043232",
"status": 400,
"error": "Bad Request",
"message": "DueDate must not be null"
}
I hope this helps. For details on class level constraints, hav a look at this video.
In my projects, this usually happens when I change my code from lets say Entity to DTO and forget to add #ModelAttribute to my DTO parameter.
If this also happened to you, try adding #ModelAttribute("offer") to your DTO parameter.
I want to save #lob(blob) data into DB using JPA repository.
I am trying something like below
User user = new user();
user.setProfile(<<BLOB DATA>>);
I want to set user profile as blob data and save to db
we use #Lob to save the data in BLOB or CLOB
Entity:
#Entity
#Table(name="USER_LOB_TABLE")
public class User {
#Id
private Long userId;
#Lob
#Column(name="PROFILE")
private byte[] profile;
//getters and setters
}
JpaRepository:
public interface UserRepository extends JpaRepository<User,Long>{}
Service layer:
userRepository.save(new User(1L,"hellodgasdgasdgasdgadsgas".getBytes()));
output:
user_id,profile
1,BLOB
Why not use Spring Content JPA?
pom.xml
<!-- Java API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-jpa-boot-starter</artifactId>
<version>0.0.11</version>
</dependency>
<!-- REST API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest-boot-starter</artifactId>
<version>0.0.11</version>
</dependency>
User.java
#Entity
public class User {
#Id
private Long userId;
#ContentId
private String contentId;
#ContentLength
private long contentLength = 0L;
// if you have rest endpoints
#MimeType
private String mimeType = "text/plain";
JpaRepository
public interface UserRepository extends JpaRepository<User,Long>{}
UsersContentStore.java
#StoreRestResource(path="usersContent")
public interface UsersContentStore extends ContentStore<User, String> {
}
This will also give you REST Endpoints (# /usersContent) for handling your user's content.