MockMvc ignores JsonFormat jackson annotation - spring-mvc

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);
}
}

Related

#Valid not working with #RequestBody in Spring3.0.5

#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"
}

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

Swagger UI not working when Spring controller uses parameter Map

We are using Swagger and Spring Fox version 2.5.0, POM entry below. When we create a Spring MVC controller that has uses a parameter Map (see example below), then the Swagger-UI page does not properly generate. The controller in question does not appear on the Swagger-UI page and none of the controllers that come after it appear also (in alphabetical order).
#RequestMapping(value = "/resource/", method = RequestMethod.GET, produces = {"application/json"})
public void get(#RequestParam MultiValueMap<String, String> params) {
//code
}
When the params Map is removed, then everything is fine. Any idea what the issue could be or how to get around it?
Below is more info that may or may not be useful.
the dependencies:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.5.0</version>
</dependency>
the Swagger config:
#Configuration
#EnableSwagger2
public class SwaggerConfiguration {
#Bean
public Docket api() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.paths(PathSelectors.any())
.build();
docket.ignoredParameterTypes(Principal.class);
return docket;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("some app")
.description("some description")
.build();
}
}

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.

Spring MVC integration tests with Spring Security

I'm trying to test my login page using mvc-test.
I was working pretty good before I added spring security.
My code is:
mockMvc.perform(
post("j_spring_security_check")
.param(LOGIN_FORM_USERNAME_FIELD, testUsernameValue)
.param(LOGIN_FORM_PASSWORD_FIELD, testPasswordValue))
.andDo(print())
.andExpect(status().isOk())
.andExpect(model().attribute(LOGIN_PAGE_STATUS_VALUE, LOGIN_PAGE_STATUS_FALSE_INDICATOR));
Test class has correct annotations added:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(locations = {"classpath:security-context.xml", "classpath:applicationContext.xml", "classpath:test-contexts/test-context.xml" })
My filter is defined (in web.xml):
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
When I try to add web.xml in #ContextConfiguration it fails, when I remove it I'm getting an Exception:
java.lang.AssertionError: Status expected:<200> but was:<405>
Is there any way to add DelegatingProxyFilter to test context with configuration defined in my security-context.xml to make it works? I tried few tutorials with injecting FilterProxyChain, but it is not working in my case.
Can someone help me with that?
Thanks in advance
UPDATE: Spring Security 4+ provides out of the box integration with MockMvc. In order to use it ensure you use apply(springSecurity()) as shown below:
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
#WebAppConfiguration
public class MockMvcSecurityTests {
#Autowired
private WebApplicationContext context;
private MockMvc mvc;
#Before
public void setup() {
mvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
}
...
}
Original Answer
I'm not sure what you mean by "When I try to add web.xml in #ContextConfiguration it fails", however, you can use Spring Test MVC to validate Spring Security. There is a very good example outlined in the spring-test-mvc project.
The basic outline would look something like this:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(locations = {"classpath:security-context.xml", "classpath:applicationContext.xml", "classpath:test-contexts/test-context.xml" })
public class MyTests {
#Autowired
private FilterChainProxy springSecurityFilterChain;
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
.addFilters(this.springSecurityFilterChain).build();
}
}
The idea is that you #Autowire the FilterChainProxy (what the DelegatingProxyFilter delegates to) and instruct MockMvc to use the FilterChainProxy.
NOTE spring-test-mvc is integrated into spring-test-3.2+ and a separate project for Spring 3.1.x, so you can use the example fairly interchangeably (spring-test-mvc does not have support for #WebAppConfiguration and has to use WebContextLoader instead).
Add in pom.xml
<repository>
<id>spring-snaspho</id>
<url>http://repo.springsource.org/libs-milestone/</url>
</repository>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>4.0.0.M1</version>
</dependency>
and use org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors for authorization request. See the sample usage at https://github.com/rwinch/spring-security-test-blog (https://jira.spring.io/browse/SEC-2592)

Resources