I've been trying for days to find a similar problem online and can't seem to find anything so I am asking my question here.
I have a controller:
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#Validated
#RestController
#RequestMapping("/data")
public class TheController {
private final TheService theService;
#Autowired
public TheController(TheService theService) {
this.theService = theService;
}
#PostMapping(path = "/data", consumes = {MediaType.APPLICATION_JSON_VALUE}, produces = {MediaType.TEXT_PLAIN_VALUE})
public ResponseEntity<String> saveData(#Valid #RequestBody Data data) {
subscriptionDataFeedService.sendData(data.getDataList());
return ResponseEntity.ok()
.body("Data successful.");
}
}
I have the request body class:
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class Data {
#NotEmpty(message = "Data list cannot be empty.")
#JsonProperty(value = "dataArray")
List<#Valid DataOne> dataList;
}
I have the DataOne class:
import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class DataOne {
private #NotBlank String currency;
private #NotBlank String accountNumber;
private #NotBlank String finCode;
private String poNumber;
private #NotBlank String invoiceNumber;
private #NotNull Address billTo;
private #NotNull Address soldTo;
private #NotNull LocalDate invoiceDate;
private #NotBlank String billingPeriod;
private #NotNull LocalDate paymentDueDate;
private #NotNull BigDecimal amountDue;
#JsonProperty(value = "activitySummary")
private #NotNull List<#Valid ProductSummary> productSummaryList;
#JsonProperty(value = "accountSummary")
private #NotNull List<#Valid AccountSummary> accountSummaryList;
#JsonProperty(value = "transactions")
private #NotNull List<#Valid Transaction> transactionList;
private #NotNull PaymentByACH paymentByACH;
private #NotNull Address paymentByCheck;
private #NotNull CustomerServiceContact customerServiceContact;
}
And I will include the Address class:
import javax.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class Address {
private #NotBlank String name;
private #NotBlank String address1;
private String address2;
private #NotBlank String city;
private #NotBlank String state;
private #NotBlank String postalCode;
}
I omitted some of the other classes because they aren't needed for my question.
So the problem I am having is that the #Valid annotation is able to validate everything except for the nested classes inside DataOne that aren't a list. In other words, it cannot validate the fields inside Address, PaymentByACH, etc. However, it is able to validate that those objects are #NotNull but is unable to validate the fields inside those classes.
The #Valid is unable to validate the name, address 1, city, etc fields inside of Address. Whenever I add an #Valid tag in front of the Address field inside DataOne I get an HV000028: Unexpected exception during isValid call exception.
How can I validate the nested fields inside of the Address object or any of the nested objects?
TL;DR: The objects that are a list, such as List<#Valid Transaction> transactionList; does validate the fields inside of Transaction but the code does not validate the fields inside of Address.
Great question.
I think you're slightly misusing the #Valid annotation.
How can I validate the nested fields inside of the Address object or
any of the nested objects?
#Valid shouldn't be prefixed to fields you want to validate. That tool is used specifically for validating arguments in #Controller endpoint methods (and sometimes #Service methods). According to docs.spring.io:
"Spring MVC has the ability to automatically validate #Controller
inputs."
It offers the following example,
#Controller
public class MyController {
#RequestMapping("/foo", method=RequestMethod.POST)
public void processFoo(#Valid Foo foo) { /* ... */ }
}
The only reason you should use #Valid anywhere besides in the parameters of a controller (or service) method is to annotate complex types, like lists of objects (ie: DataOne: productSummaryList, accountSummaryList, transactionList). These docs have details for implementing your own validation policy if you'd like.
For your practical needs, you should probably only be using #Valid on controller level methods and the complex types for models referenced by that method. Then use field-level constraints to ensure you don't get things like negative age. For example:
#Data
...
public class Person {
...
#Positive
#Max(value = 117)
private int age;
...
}
Check out this list of constraints you can use from the spring docs. You're already using the #NotNull constraint, so this shouldn't be too foreign. You can validate emails, credit cards, dates, decimals, ranges, negative or positive values, and many other constraints.
Related
This question already has answers here:
How to fix org.hibernate.LazyInitializationException - could not initialize proxy - no Session
(24 answers)
Closed last year.
I'm trying to make a database based API I have a huge load of data but every time I try to bring the data even with pageable property I get this error:
{
"timestamp": "2022-01-12T01:34:01.851+00:00",
"status": 500,
"error": "Internal Server Error",
"trace": "org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: br.com.leomanzini.space.flight.news.model.Article.launches, could not initialize proxy - no Session\r\n\tat org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:612)\r\n\tat org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)\r\n\tat org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:591)\r\n\tat org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)\r\n\tat org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:387)\r\n\tat java.base/java.lang.Iterable.forEach(Iterable.java:74)\r\n\tat br.com.leomanzini.space.flight.news.dto.ArticlesDTO.<init>(ArticlesDTO.java:65)\r\n\tat br.com.leomanzini.space.flight.news.service.ArticleService.lambda$findAll$0(ArticleService.java:30)\r\n\tat java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)\r\n\tat java.base/java.util.ArrayList$Itr.forEachRemaining(ArrayList.java:1032)\r\n\tat java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)\r\n\tat java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)\r\n\tat java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)\r\n\tat java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)\r\n\tat java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)\r\n\tat java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)\r\n\tat org.springframework.data.domain.Chunk.getConvertedContent(Chunk.java:173)\r\n\tat org.springframework.data.domain.PageImpl.map(PageImpl.java:106)\r\n\tat br.com.leomanzini.space.flight.news.service.ArticleService.findAll(ArticleService.java:30)\r\n\tat br.com.leomanzini.space.flight.news.controller.SpaceFlightsApiController.findAll(SpaceFlightsApiController.java:28)\r\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:566)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\r\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:655)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:764)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.base/java.lang.Thread.run(Thread.java:834)\r\n",
"message": "failed to lazily initialize a collection of role: br.com.leomanzini.space.flight.news.model.Article.launches, could not initialize proxy - no Session",
"path": "/articles"
}
At the database I have an amount of 11795 articles and their respectives relationship with others tables, there is a way to optimize this load or just make it works?
Article entity:
import lombok.*;
import javax.persistence.*;
import java.util.List;
#Entity
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "article")
public class Article {
#Id
#EqualsAndHashCode.Include
private Long id;
#Column(nullable = false)
private Boolean featured;
#Column(nullable = false)
private String title;
#Column(nullable = false)
private String url;
#Column(name = "image_url", nullable = false)
private String imageUrl;
#Column(name = "news_site", nullable = false)
private String newsSite;
#Column(nullable = false)
private String summary;
#Column(name = "published_at", nullable = false)
private String publishedAt;
#ManyToMany(fetch = FetchType.LAZY)
private List<Launches> launches;
#ManyToMany(fetch = FetchType.LAZY)
private List<Events> events;
#Column(name = "inserted_by_human")
private Boolean insertedByHuman = false;
}
Events and Launches entities:
import lombok.*;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class Events {
#Id
#EqualsAndHashCode.Include
private Long id;
private String provider;
}
import lombok.*;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class Launches {
#Id
#EqualsAndHashCode.Include
private String id;
private String provider;
}
The repository is just a interface with JpaRepository and the Article as entity.
The service class:
import br.com.leomanzini.space.flight.news.dto.ArticlesDTO;
import br.com.leomanzini.space.flight.news.model.Article;
import br.com.leomanzini.space.flight.news.repository.ArticleRepository;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
#Service
#AllArgsConstructor
public class ArticleService {
#Autowired
private final ArticleRepository articleRepository;
public Page<ArticlesDTO> findAll(Pageable pageable) {
Page<Article> articleList = articleRepository.findAll(pageable);
return articleList.map(article -> new ArticlesDTO(article));
}
}
If I just use my entity as a return, the methods work, but when I convert the same to dto the application breaks. The dto class is below:
import br.com.leomanzini.space.flight.news.model.Article;
import lombok.*;
import javax.management.ConstructorParameters;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class ArticlesDTO implements Serializable {
#NotEmpty
#EqualsAndHashCode.Include
private Long id;
#NotEmpty
private String title;
#NotEmpty
private String url;
#NotEmpty
private String imageUrl;
#NotEmpty
private String newsSite;
#NotEmpty
private String summary;
#NotEmpty
private String publishedAt;
#NotEmpty
private String updatedAt;
#NotEmpty
private Boolean featured;
#Valid
private List<LaunchesDTO> launches;
#Valid
private List<EventsDTO> events;
public ArticlesDTO (Article article) {
id = article.getId();
title = article.getTitle();
url = article.getUrl();
imageUrl = article.getImageUrl();
newsSite = article.getNewsSite();
summary = article.getSummary();
publishedAt = article.getPublishedAt();
updatedAt = article.getPublishedAt();
featured = article.getFeatured();
launches = new ArrayList<>();
article.getLaunches().forEach(launch -> {
LaunchesDTO launchesDTO = new LaunchesDTO(launch.getId(), launch.getProvider());
launches.add(launchesDTO);
});
events = new ArrayList<>();
article.getEvents().forEach(event -> {
EventsDTO eventsDTO = new EventsDTO(event.getId(), event.getProvider());
events.add(eventsDTO);
});
}
}
There is anyway to fix the error and make it works? Something to accelerate the database load or something else?
With FetchType.LAZY, the query that is used for retrieving those fields will be executed only when it is accessed for the first time. In order to do this, Hibernate creates and configures proxy classes for our entity classes (that's why we also should not declare our entity classes to be final if we want to use the lazy load feature).
When Hibernate initializes proxies, it requires a Session in order to do the task. That's why when you don't add the #Transactional annotation to the service method, it will throw out an LazyInitializationException...no Session.
Beside the solution above, if you don't want to add the #Transactional annotation, you can set hibernate.enable_lazy_load_no_trans property to true.
<property
name="hibernate.enable_lazy_load_no_trans"
value="true"/>
But this solution is considered to be an anti-pattern. It will create a new Session everytime you try to lazy-load. You can read it more here. The hibernate.enable_lazy_load_no_trans Anti-Pattern
The proposed answer was that in the service class, the #Transactional(readOnly = true) attribute has been enabled, it works fine to resolve the error
failed to lazyly initialize a collection of role: br.com .
leomanzini.space.flight.news.model.Article.launches, could not
initialize proxy.
The method at service class looked like this:
import br.com.leomanzini.space.flight.news.dto.ArticlesDTO;
import br.com.leomanzini.space.flight.news.model.Article;
import br.com.leomanzini.space.flight.news.repository.ArticleRepository;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service
#AllArgsConstructor
public class ArticleService {
#Autowired
private final ArticleRepository articleRepository;
#Transactional(readOnly = true)
public Page<ArticlesDTO> findAll(Pageable pageable) {
Page<Article> articleList = articleRepository.findAll(pageable);
return articleList.map(article -> new ArticlesDTO(article));
}
}
And the requisition working fine!
I need to convert entity's field on fetch and according to this official example I've tried to do that with custom setter:
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
#Table("entity")
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder(builderClassName = "EntityBuilder")
public class Entity {
#Id
private String someId;
#Transient
private String entityName;
#Column("entity_name")
public String getEntityNameUnmodified() {
return this.entityName;
}
#Column("entity_name")
public void setEntityNameUnmodified(String em) {
this.entityName = em + " Some modification";
}
}
But this completely doesn't work and as a result I get Entity with entityName == null.
I've downloaded GitHub example and run it locally and everything worked. What's wrong with my code?
My code didn't work because of missing #AccessType(AccessType.Type.PROPERTY) annotation.
Working solution:
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
#Table("entity")
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder(builderClassName = "EntityBuilder")
#AccessType(AccessType.Type.PROPERTY) // IMPORTANT !!!
public class Entity {
#Id
private String someId;
#Transient
private String entityName;
#Column("entity_name")
public String getEntityNameUnmodified() {
return this.entityName;
}
#Column("entity_name")
public void setEntityNameUnmodified(String em) {
this.entityName = em + " Some modification";
}
}
The thing is that Spring Data JDBC uses fields as accessors for entity's columns by default and without that annotation setters and getters are ignored. Enabling PROPERTY access type solves the problem.
Updated Spring boot to 2.2.X from 2.1.X and elastic search to 6.8.X from 6.3.X.
Got mapping exception, to resolve Mapping exception, renamed document variable to myDocument.
Now on elasticSearchRepo.SaveAll(objectTosave) value is not persisted in document.
Other properties like id, category are present in the document.
Is there any way to have different fieldName and jsonProperty?
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
#NoArgsConstructor
#Data
#EqualsAndHashCode
#ToString
#Document(indexName="my_document_index", type="information", createIndex=false)
#JsonIgnoreProperties(ignoreUnKnown = true)
#JsonInclude(Include.NON_NULL)
public class MyInstance
{
#Field
private String id;
#Field
private String category;
#Field
#JsonProperty("document")
private MyObject mydocument;
/** JSON Creator **/
#JsonCreator
public MyInstance(#JsonProperty("id") id, #JsonProperty("category") category,
#JsonProperty("document") mydocument)
{
this.id = id;
this.category = category;
this.mydocument = mydocument;
}
}
No need to annotate the id property with #Field, you should rather put #Id there. Although this is not needed, as the name of the property is enough, it makes it clearer what it is.
As for the mydocument property not being persisted: It is but in Elasticsearch with the name mydocument. The #JsonProperty("document") defines the name of this property in JSON when mapped by Jackson, when you get this in over a REST endpoint for example. Renaming to mydocument inhibits the error that the property is interpreted as id property.
But I think you want to have as document in Elasticsearch as well. You can define the name of a property in Elasticsearch by setting it in the #Field annotation:
#Document(indexName="my_document_index", createIndex=false)
public class MyInstance
{
#Id
private String id;
#Field
private String category;
#Field(name = "document")
#JsonProperty("document")
private MyObject mydocument;
}
I have created a pretty small and simple Spring Boot app using the Oracle database and some JPA queries.
This is the code snippet which is not returning data, which is actually exists in database.
letterRecipientNonOas = letterRecipientNonOasRepository
.findById(Long.valueOf(letterRecipientDTO.getNonOas().getId()))
.orElseThrow(() -> new EntityNotFoundException(LetterRecipientNonOas.class,
Constant.MESSAGE_ENTITY_NOT_FOUND));
here findById is returning empty result set.
this is my repository
package com.care.document.repository;
import java.util.List;
import java.util.Optional;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import com.care.document.model.LetterRecipientNonOas;
/**
* The Interface LetterRecipientNonOasRepository.
*/
#Repository
public interface LetterRecipientNonOasRepository extends PagingAndSortingRepository<LetterRecipientNonOas, Long> {
Optional<LetterRecipientNonOas> findByLetterId(Long id);
Optional<LetterRecipientNonOas> findByTitleIgnoreCase(String title);
List<LetterRecipientNonOas> findByTitleContainingIgnoreCase(String title);
List<LetterRecipientNonOas> findAllByTitleIgnoreCaseAndIdNot(String title, Long recipientId);
List<LetterRecipientNonOas> findAllByIdAndLetterId(long id, long letterId);
}
and this is my model class:
package com.care.document.model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import org.springframework.lang.Nullable;
import com.care.admin.model.BaseEntity;
import com.care.admin.util.CommonUtil;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.FieldDefaults;
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#FieldDefaults(level = AccessLevel.PRIVATE)
#Entity
#Table(name = "letter_recipient_non_oas")
public class LetterRecipientNonOas extends BaseEntity implements Serializable {
#Id
Long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "letter_id")
Letter letter;
Integer recipientType; // Action/Info
//byte recipientSubType; // Internal/External/NonOAS
byte recipientCategory; //Internal/External
int orderNo;
String title;
#Nullable
String remarks;
String address;
#PrePersist
private void prePersist() {
this.id = CommonUtil.generateID(this.atRegion);
}
}
I tested, tried different ways but of no use.
There are a couple of scenarios how one might get this impression:
You are looking at the wrong database.
The data isn't there yet when you try to load it, but is when you check.
JPAs caches are known to create such scenarios rather efficiently.
The data looks a little different than you think. This could be caused by invisible or easy to miss content like spaces or even control characters.
You check the database within the transaction that created the data or with a session that allows dirty reads and the insert that created the data wasn't committed yet.
Hi i am following an example I found
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-jsr303-valid-example/
The problem is that no errors are found in my profile that I post. I should be. Why can this happend?
#Test
#Ignore
public void anotherTest() {
Profile profile = ProfileUtil.getProfile();
profile.setEmail("user#mail.com");
profile.setSex("dafjsgkkdsfa");
BindingResult bindingResult = new BeanPropertyBindingResult(profile, "profile");
userController.postUser(new ModelMap(), profile, bindingResult);
if (bindingResult.hasErrors()) {
System.out.println("errors");
}
assertTrue(bindingResult.hasErrors());
profileService.deleteProfile(profile);
}
#RequestMapping(value = "/", method = RequestMethod.POST)
public View postUser(ModelMap data, #Valid Profile profile, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
System.out.println("No errors");
return dummyDataView;
}
data.put(DummyDataView.DATA_TO_SEND, "users/user-1.json");
profileService.save(profile);
return dummyDataView;
}
Edit:
This is the Profile. I am testing the sex now so I guess thats what is important.
package no.tine.web.tinetips.domain;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import no.tine.web.tinetips.util.CommonRegularExpressions;
import org.hibernate.validator.constraints.NotBlank;
#Entity
public class Profile {
#Id
#GeneratedValue
private Long id;
#NotNull(message = "profile.email.null")
#NotBlank(message = "profile.email.blank")
#Size(max = 60, message = "profile.email.maxlength")
#Pattern(regexp = CommonRegularExpressions.EMAIL, message = "profile.email.regex")
#Column(name = "Email", unique = true)
private String email;
#Pattern(regexp = "^[M|F]{1}$", message = "profile.sex.regex")
#Size(max = 1, message = "profile.sex.maxlength")
private String sex;
}
Basically you instantiated a POJO with this.userController = new UserController(), then called its method this.controller.postUser(...). Just simple Java with a simple object, without any relation to Spring and Spring MVC : #Valid is not taken into account.
If you want to make it work, you will have to give your test class some Spring information, with #RunWith(SpringJUnit4ClassRunner.class) and #ContextConfiguration(...). Then, for the Spring MVC part, you will have to mock a request call on your Controller through some Spring MVC facilites. It is done differently if you use Spring MVC 3.0- or 3.1+. For more information and actual code, see this post and its answers, for example.