#Valid not working with #RequestBody in Spring3.0.5 - spring-mvc

#Valid is not working with RequestBody in Sptring 3.0.5. Below is code snippets . Please suggest what is causing the issue.
pom.xml file
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.0.2.GA</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
Conroller:
#RequestMapping(value = "/ValidateCustomer", method = RequestMethod.POST, headers="content-type=application/json")
#ResponseBody
public String validateCustomer(#Valid #RequestBody Customer customer) throws Exception {
// further processing"
return "Validated";
}
Customer class:
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
public class Customer {
#NotNull
private String userId;
#NotNull
private String firstName;
#NotNull
private String lastName;
#NotNull
private String companyName;
/* getter and setter methods */
}
Below is the payload requested from postman which should fail to the request, but receiving success message.
{
"firstName":"abc",
"lastName": "xyz",
"companyName":"abc Corp"
}

Related

No converter for [class java.util.ArrayList] with preset Content-Type 'null'

So, while i was dealing with RestApi and trying to GET a request form POSTMAN , this throws an error stating
No converter for [class java.util.ArrayList] with preset Content-Type
'null'
I was expecting the requestmapping will return a list of array in json data format.
here is my code below.
#RestController
#RequestMapping("/postman")
public class PostManController {
#Autowired
private PostmanProductDao postmanProductDao;
#ResponseBody
#GetMapping(value = "/hi")
public String showPostman(){
return "Hey, I am the postman. the new Buddy.";
}
#ResponseBody
#GetMapping (value = "/Products",
produces = MediaType.APPLICATION_JSON_VALUE)
public List<PostmanProduct> getProducts(){
return this.postmanProductDao.getProducts();
}
}
#Component
public class PostmanProductDao {
List<PostmanProduct> list;
public postmanProductDao(){
list = new ArrayList<>();
list.add(new postmanProduct(100,"Ipod","Apple"));
list.add(new postmanProduct(102,"Samsung Buds","Samsung"));
}
public List<PostmanProduct> getProducts(){
return list;
}
}
So adding this dependecny resolved the issue. There was an issue with the version 2.13.4.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.4.2</version>
</dependency>

How to return Bean class Object as JSON in Rest Controller in Spring MVC

Here my controller is like,
#RequestMapping(value = "/restCallRequest", headers =
"Accept=application/json", method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<Void> callRequest(#RequestBody CallRequestData
requestData, UriComponentsBuilder ucBuilder) {
if (requestData.getIvrName().isEmpty()) {
return new ResponseEntity<Void>(HttpStatus.CONFLICT);
}
System.err.println("IVER Name is "+requestData.getIvrName()+" lsit "+requestData.getContactList().get(0));
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/restCallRequest").buildAndExpand(requestData).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
And my Bean Class is,
#Entity
public class CallRequestData {
private int id; //Auto incremented
private String ivrName;
private List<String> contactList;
public CallRequestData(int id, String ivrName, List<String> contactList) {
this.id = id;
this.ivrName = ivrName;
this.contactList = contactList;
}
//setters And Getters
Here my POSTMAN send JSON
{
"ivr_name":"welcome",
"contactList":[
"9040210495",
"958045830"
]
}
And Also i want Response as like Request,
{
"ivr_name":"welcome",
"contactList":[
"9040210495",
"958045830"
]
}
How can i solve it. Thanks In Advance.
add dependency in pom.xml
<dependency>
<groupId>net.sf.flexjson</groupId>
<artifactId>flexjson</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.3</version>
</dependency>
Write one method in controller.
public String toJson(User bean) {
return new JSONSerializer().transform(new DateTransformer("MM/dd/yyyy HH:mm:ss"),java.util.Date.class).serialize(bean);
}
and pass your bean object to this method.
return new ResponseEntity<String>(toJson(bean),headers, HttpStatus.CREATED);
change return type to string in method signature public ResponseEntity<String> callRequest
NOTE: For Spring boot you can use #RestController annotation which will auto convert objects to json.
Add Jackson dependencies
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
<scope>provided</scope>
</dependency>
and add
#RequestMapping(value="/endpoint",produces="application/json",method=RequestMethod.POST)
produces="application/json" to the request mapping. \
Now whatever, bean is defined after #ResponseBody will get returned as a json object to client. There is no need to parse it as json externally.
I don't understand why you make all this option.
Is so easy.
If your controller is annotated with #RestController, you have just to return the object like this:
#RequestMapping..................................)
public ResponseEntity<CallRequestData> callRequest(#RequestBody CallRequestData
requestData, UriComponentsBuilder ucBuilder) {
......... code here ......
return new ResponseEntity<>(requestData, HttpStatus.CREATED);
}
Set the return type on the response entity and then return just return a new instance of ResponseEntity it like this.
I suggest you avoid multiple RETURN, assign a variable to the ResponseEntity and return just once at the end of the method

MockMvc ignores JsonFormat jackson annotation

I set-up a REST API with Spring MVC and Spring HATEOAS.
In one of the DTOs I put a JsonFormat on a ZonedDateTime field.
Running the server gives me the expected date format (yyyyMMdd), but with testing the annotation is ignored and I get something like 1454281200.000000000. So it looks like when testing the annotation is ignored totally. I tried the #JsonIgnore annotation, but that on was working.
No matter I use MockMvcBuilders.webAppContextSetup(wac).build() or MockMvcBuilders.standaloneSetup(membersController).build() the time is simply not converted to the JsonFormat as expected.
Anyone any idea's what going wrong here? I expect some configuration issue, but I don't know where to look at.
Discovered that the aDate on the Resource is serialised properly, but the xxxDTO.aDate is not serialised properly.
Resource
public class XxxResource extends Resource<XxxDTO> {
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyyMMdd")
private ZonedDateTime aDate;
public XxxResource(XxxDTO xxxDTO) {
super(xxxDTO);
this.aDate = xxxDTO.getADate();
}
}
DTO
public class XxxDTO {
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyyMMdd")
private ZonedDateTime aDate;
}
pom.xml
<jackson.version>2.8.3</jackson.version>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.3-RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>
<version>0.20.0.RELEASE</version>
</dependency>
Test setup
#RunWith(MockitoJUnitRunner.class)
public class SomeTest {
XxxController xxxController = new XxxController(XxxService, new XxxResourceAssembler(),
new PagedResourcesAssembler<>(new HateoasPageableHandlerMethodArgumentResolver(), null));
this.mockMvc = MockMvcBuilders.standaloneSetup(xxxController).setCustomArgumentResolvers
(new PageableHandlerMethodArgumentResolver()).build();
}
The endpoints are set up through a web.xml and the WebMvcConfig is like this:
#Configuration
#EnableWebMvc
#EnableSpringDataWebSupport
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new PageableHandlerMethodArgumentResolver());
}
#Bean
public PagedResourcesAssembler pagedResourcesAssembler() {
return new PagedResourcesAssembler(new HateoasPageableHandlerMethodArgumentResolver(), null);
}
}

Hibernate validator #NotEmpty not working spring boot and jackson

I have the following class which has errorRequests with #NotEmpty annotation.
public class ErrorsRequests implements Serializable {
private static final long serialVersionUID = -727308651190295062L;
private String applicationName;
#NotEmpty
#Valid
#JsonProperty("errors")
private List<ErrorsRequest> errorRequests;
My Controller looks like the following:
#Autowired
#Qualifier("errorStreamValidator")
private Validator errorStreamValidator;
#RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> errorReporting(#NotNull #PathVariable String applicationName,
#Valid #NotNull #RequestBody ErrorsRequests errorsRequests, BindingResult results) {
I have the required hibernate validator classes in my classpath.
When I input the following JSON :
{
"errorss": [
]
}
The #NotEmpty validation is not kicked off at all. Hibernate validation only works if the json has errors element in it as below
{
"errors": [
]
}
Can I make the first case also work ?
You are using the annotations in the wrong way and your controller is also missing an annotation.
You should annotate your controller with #Validated:
#Validated
#RestController
#RequestMapping("/mycontroller")
public class MyController { ... }
And in your model class you need to place the annotations like this:
#NotEmpty
private List<#Valid Foo> foo;
The #Valid annotation will check if the items inside the list are also valid.
Check that you have included this dependency in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Aspectj advice not getting executed

I am trying to code a simple AspectJ implementation but the Advice is not getting executed.
The LoggingAspect Class is getting initiated as in the console I can see s.o.p of constructor
This is logging aspect
getting printed when the ApplicationContext is loaded and controllerAspect is initialized. When I run the main method , the output is
Name: John Age :12
What I was expecting was the s.o.p for #Before advice should be printed first and then for getter methods #AfterReturning s.o.p should be printed.
There is no compilation error , the program is running but advice is not getting executed.
According to the pointcut, the advice should get implemented on all methods of the Customer class.
I went through some of the similar problems posted here , but could not figure out what was the issue with my implementation.
Can any one figure the mistake I am making and provide the resolution ?
Here is the snippet servlet-context.xml
<context:component-scan base-package="main.com.controller"/>
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven></annotation-driven>
<aop:aspectj-autoproxy/>
<!-- AOP support -->
<bean id='controllerAspect' class='main.com.logging.LoggingAspect' />
<beans:bean id="cust" class="main.com.dtos.Customer"</beans:bean>
<resources mapping="/resources/**" location="/resources/" />
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/"/>
<beans:property name="suffix" value=".jsp"/>
</beans:bean>
The LoggingAspect class is :
#Aspect
public class LoggingAspect {
public LoggingAspect() {
System.out.println("This is logging aspect");
}
#Pointcut("execution(* com.dtos.*.*(..))")
public void getMethodPointcut() {}
#AfterReturning(pointcut = "getMethodPointcut()", returning="retVal")
public void afterReturningAdvice(Object retVal) {
System.out.println("Returning:" + retVal.toString() );
}
#Before("getMethodPointcut()")
public void printBefore(JoinPoint jp ) {
System.out.println("Before calling method:"+jp.getSignature());
}
Customer class is :
#Size(max=30, min=3)
#NotNull
private String name;
#Max(150)
#NotNull
private String age;
public Customer() {}
public Customer(String sName, String sAge) {
name = sName;
age = sAge;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
#Override
public String toString() {
return "Customer [name=" + name + ", age=" + age + "]";
}
Main method is :
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath:servlet- context.xml");
Customer cust = (Customer)context.getBean("cust");
cust.setAge("12");
cust.setName("John");
String name = cust.getName();
String age = cust.getAge();
System.out.println("Name: "+name+" Age :"+age);
}
Aspectj POM dependencies
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.4</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.7.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
Just so as to enable you to close the question by accepting an answer, I am repeating my answer from the comment:
Your Spring config implies it is main.com.dtos.Customer, your aspect pointcut is looking for com.dtos.* (without main. prefix) though.

Resources