We have upgraded the project technology from Java servlet to Spring Boot. It's working fine for single user transaction mode, but it's not working multiple users test.
My Project configuration
UI - angular
Business Logic- Java Spring Boot
back end - No SQL get call
No hibernate
Session - stateless session
We don't process based on the user's session. We process only employee id and case id(75 % get request, 25 % post request). it's working fine for single user time. LoadNinja load test run 50 users time - we will get another user's response to me.
My name is Apple if I am requesting for my details(load ninja run the same process for 50 user test simultaneously) to the server , but i am getting response as Orange user's details. Sometimes I am getting a Null pointer exception.
I am unable to trace the cause of the issue - Could you please advise for project configuration changes.
Thanks in advance.
EmployeeController.java
package com.apa.documentprocessor.constants;
import java.io.IOException;
import javax.xml.bind.JAXBException;
import org.apache.commons.httpclient.HttpException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
#RequestMapping("/employee")
public class EmployeeController {
#Autowired
EmployeeService employeeservice;
#Autowired
Employee employee;
#RequestMapping("/getDetails")
public void getEmployeeDetails() throws HttpException, IOException, JAXBException {
employee.setEmpId("100");
employee.setEmpName("Nuno");
employee.setDept("Research");
employee.setLocation("India");
EmployeePerformance emp = employeeservice.EmployeeDetails(employee);
System.out.println(emp.toString());
}
}
EmployeeService.java
package com.apa.documentprocessor.constants;
import java.io.IOException;
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.stereotype.Component;
import org.xml.sax.InputSource;
#Component
public class EmployeeService {
#Autowired
EmployeePerformance empPerformance;
#Autowired
private AutowireCapableBeanFactory beanFactory;
public EmployeePerformance EmployeeDetails(Employee emp) throws HttpException, IOException, JAXBException {
this.empPerformance = beanFactory.createBean(EmployeePerformance.class);
this.empPerformance = getDetails(emp);
return empPerformance;
}
private EmployeePerformance getDetails(Employee emp) throws HttpException, IOException, JAXBException {
String result;
String url=emp.getEmpName();
HttpClient client = new HttpClient();
GetMethod method = new GetMethod(url);
method.addRequestHeader("3454362523", emp.getEmpId());
client.executeMethod(method);
result = method.getResponseBodyAsString();
JAXBContext jaxbContext = JAXBContext.newInstance(EmployeePerformance.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
EmployeePerformance empPerformance = (EmployeePerformance) jaxbUnmarshaller
.unmarshal(new InputSource(new StringReader(result)));
empPerformance.setProject("Banking");
empPerformance.setRating("Good");
return empPerformance;
}
}
EmployeePerformance.java
package com.apa.documentprocessor.constants;
import org.springframework.stereotype.Component;
#Component
public class EmployeePerformance {
String empName;
String rating;
String project;
String position;
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getRating() {
return rating;
}
public void setRating(String rating) {
this.rating = rating;
}
public String getProject() {
return project;
}
public void setProject(String project) {
this.project = project;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
Employee.java
package com.apa.documentprocessor.constants;
import org.springframework.stereotype.Component;
#Component
public class Employee {
String empId;
String empName;
String dept;
String location;
public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
Your code is flawed, don't make Employee nor EmployeePerformance spring managed beans. Just construct a new instance when you need one. The fact that one uses Spring doesn't mean everything needs to be managed by Spring.
#RequestMapping("/employee")
public class EmployeeController {
#Autowired
EmployeeService employeeservice;
#RequestMapping("/getDetails")
public void getEmployeeDetails() throws HttpException, IOException, JAXBException {
Employee employee = new Employee();
employee.setEmpId("100");
employee.setEmpName("Nuno");
employee.setDept("Research");
employee.setLocation("India");
EmployeePerformance emp = employeeservice.EmployeeDetails(employee);
System.out.println(emp.toString());
}
}
Regarding the use of HttpClient don't construct one each time, instead reuse it, or even better use RestTemplate which does all of that out-of-the-box, including the marshalling.
#Component
public class EmployeeService {
private final RestTemplate http;
public EmployeeService(RestTemplate http) {
this.http=http;
}
public EmployeePerformance EmployeeDetails(Employee emp) throws HttpException, IOException, JAXBException {
return getDetails(emp);
}
private EmployeePerformance getDetails(Employee emp) throws HttpException, IOException, JAXBException {
String url=emp.getEmpName();
RequestEntity req = RequestEntity.get(url).header("3454362523", emp.getEmpId()).build();
EmployeePerformance empPerformance = http.exchange(req, EmployeePerformance.class).getBody();
empPerformance.setProject("Banking");
empPerformance.setRating("Good");
return empPerformance;
}
}
In your configuration you need to add the following
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.requestFactory(HttpComponentsClientHttpRequestFactory.class).build();
}
With this you are not sharing state anymore and reusing heavy objects instaed of constructing them each time you need them.
Related
Hello there I am new to spring boot, i am getting this error since a while, unfortunately can't fix it. I am googling since then but still not find what i did wrong. I believe the error exists in the Service Class. I tried to remove the field injection ( #Autowired) and implemented as a constructor injection but that did not work as well Find below my code:
Entity:
package com.devops.maven.cars_api_maven.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import javax.persistence.*;
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
#Entity
#Table(name = "CARS")
#SequenceGenerator(name="seq", initialValue=4, allocationSize=100)
public class Car {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
private Long id;
String manufacturer;
String model;
int build;
public Car() {
}
public Car(Long id, String manufacturer, String model, int build) {
this.id = id;
this.manufacturer = manufacturer;
this.model = model;
this.build = build;
}
public Long getId() {
return id;
}
public String getManufacturer() {
return manufacturer;
}
public String getModel() {
return model;
}
public int getBuild() {
return build;
}
public void setId(Long id) {
this.id = id;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public void setModel(String model) {
this.model = model;
}
public void setBuild(int build) {
this.build = build;
}
}
DAO
package com.devops.maven.cars_api_maven.repositories;
import com.devops.maven.cars_api_maven.model.Car;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface CarsRepository extends JpaRepository<Car, Long> {
}
Main
package com.devops.maven.cars_api_maven;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
#SpringBootApplication (
exclude = {DataSourceAutoConfiguration.class },
scanBasePackages={
"com.devops.maven", "com.devop.application"}
)
public class CarsApplication {
public static void main(String[] args) {
SpringApplication.run(CarsApplication.class, args);
}
}
Service Class
package com.devops.maven.cars_api_maven;
import com.devops.maven.cars_api_maven.model.Car;
import com.devops.maven.cars_api_maven.repositories.CarsRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import java.util.List;
#RestController
#RequestMapping("cars")
#Service
public class CarsController {
#Autowired
private CarsRepository repository;
#GetMapping
public List<Car> getCars() {
return repository.findAll();
}
#PostMapping
public Car addCar(#RequestBody Car car) {
return repository.save(car);
}
#SuppressWarnings("deprecation")
#GetMapping(value = "/{id}")
public Car getCarById(#PathVariable("id") long id) {
return repository.getOne(id);
}
#DeleteMapping(value = "/{id}")
public void removeCarById(#PathVariable("id") long id) {
repository.deleteById(id);
}
}
Error output:
*************************** APPLICATION FAILED TO START
Description:
Field repository in com.devops.maven.cars_api_maven.CarsController
required a bean of type
'com.devops.maven.cars_api_maven.repositories.CarsRepository' that
could not be found.
The injection point has the following annotations:
#org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type
'com.devops.maven.cars_api_maven.repositories.CarsRepository' in your
configuration.
Please remove exclude = {DataSourceAutoConfiguration.class } from below class and run again. It will fix the issue.
package com.devops.maven.cars_api_maven;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
#SpringBootApplication (
exclude = {DataSourceAutoConfiguration.class },
scanBasePackages={
"com.devops.maven", "com.devop.application"}
)
public class CarsApplication {
public static void main(String[] args) {
SpringApplication.run(CarsApplication.class, args);
}
}
I am a new beginner in Spring boot...I encounter a problem When I run my controller,
Description:
Field todoService in com.springboot.todoController.TodoController
required a bean of type 'com.springboot.todo.TodoService' that could
not be found.
Action:
Consider defining a bean of type 'com.springboot.todo.TodoService' in
your configuration.
below is my code
Todo.java
package com.springboot.todoBean;
import java.util.Date;
public class Todo {
private int id;
private String user;
private String desc;
private Date targetDate;
private boolean isDone;
public Todo() {}
public Todo(int id, String user, String desc, Date targetDate, boolean isDone) {
super();
this.id = id;
this.user = user;
this.desc = desc;
this.targetDate = targetDate;
this.isDone = isDone;
}
public int getId() {
return id;
}
public String getUser() {
return user;
}
public String getDesc() {
return desc;
}
public Date getTargetDate() {
return targetDate;
}
public boolean isDone() {
return isDone;
}
}
TodoService.java
package com.springboot.todo;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.stereotype.Service;
import com.springboot.todoBean.Todo;
#Service
public class TodoService {
private static List<Todo> todos = new ArrayList<Todo>();
private static int todoCount = 3;
static {
todos.add(new Todo(1, "Jack", "Learn Spring MVC", new Date(), false));
todos.add(new Todo(2, "Jack", "Learn Struts", new Date(), false));
todos.add(new Todo(3, "Jill", "Learn hibernate", new Date(), false));
}
public List<Todo> retrieveTodos(String user){
List<Todo> filteredTodos = new ArrayList<Todo>();
for (Todo todo : todos) {
if(todo.getUser().equals(user))
filteredTodos.add(todo);
}
return filteredTodos;
}
public Todo addTodo(String name, String desc,
Date targetDate, boolean isDone) {
Todo todo = new Todo(++todoCount, name, desc, targetDate, isDone);
todos.add(todo);
return todo;
}
public Todo retrievedTodo(int id) {
for(Todo todo: todos) {
if(todo.getId() == id)
return todo;
}
return null;
}
}
TodoController.java
package com.springboot.todoController;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.springboot.todo.TodoService;
import com.springboot.todoBean.Todo;
#RestController
public class TodoController {
#Autowired
private TodoService todoService;
#GetMapping("/users/{name}/todos")
public List<Todo> retrieveTodo(#PathVariable String name){
return todoService.retrieveTodos(name);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(TodoController.class, args);
}
}
I have added the annotation #Service to the TodoService to tell spring boot it is a bean, but it still cannot recognise, could anyone tell me how to solve this problem? thanks
Create a separate class as below for start the spring boot application. Also, please note that below class should be placed in higher level in the package hierarchy than other controller, service, etc classes.
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Your error is generated because your application is not scanning TodoService.
The mentioned code has several problems:
please make all packages lower case - java convention
please move the main in another class and annotate it with #SpringBootApplication
ex.
#SpringBootApplication
public class Application{
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
3. by default the spring boot application will scan beans contained in the package where the class from 2 is defined. You can put the class from 2 in the common package for both service and controller.
New to spring ,
i am trying to access json object in #RequestBody MYPOJO pojo which works fine , but my json data needed to be same as variable name in pojo and case sensitive. best i did find from web is here , but not synchronize with my project , i am using spring mvc. So how can i make case insensitive my json with pojo?
the way i receive json
#RequestMapping(value = "create", method = RequestMethod.POST)
public void createPost(HttpServletRequest req, HttpServletResponse resp, #Valid #RequestBody Post post,
Errors errors) throws CustomException, IOException {
json data
function jsonForPost(isEdit, id) {
var post = {};
if (isEdit) {
post.id = id;
}
post.name = $("#name").val();
return JSON.stringify(post);
}
With Spring Boot
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import com.fasterxml.jackson.databind.MapperFeature;
#Configuration
class Configs {
#Bean
public Jackson2ObjectMapperBuilderCustomizer initJackson() {
Jackson2ObjectMapperBuilderCustomizer c = new Jackson2ObjectMapperBuilderCustomizer() {
#Override
public void customize(Jackson2ObjectMapperBuilder builder) {
builder.featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
}
};
return c;
}
}
Without Spring Boot
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.fasterxml.jackson.databind.MapperFeature;
#Configuration
#EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.indentOutput(true);
builder.featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
}
}
I have a POJO with a variable name in it:
public class Pox {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and a Controller:
#RequestMapping(value = "/create", method = RequestMethod.POST)
public void createPost(HttpServletRequest req, HttpServletResponse resp, #Valid #RequestBody Pox post,
Errors errors) {
System.out.println(post.getName());
}
I have tested with Postman with:
name, Name, NAme, nAme.
All of them worked.
With springboot using the application.yml file =>
spring:
jackson:
mapper:
accept-case-insensitive-properties: true
I am new to spring boot, and I'm trying spring boot security on my sample application and i'm using MongoDB.
I'm facing some issue. I'm using POSTMAN to test the web services that I developed.
I am not able to hit login method using POSTMAN.
Here is my main application
import org.joda.time.DateTime;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
#SpringBootApplication
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
#Bean
CommandLineRunner init(final UserRepository userRepository, final UserRoleRepository userRoleRepository) {
return new CommandLineRunner() {
#Override
public void run(String... arg0) throws Exception {
UserRole usRole = new UserRole();
usRole.setUroName("Admin");
usRole.setUroCode("admin");
usRole.setUroType("admin");
usRole.setUroCreatedDttm(new DateTime().toString());
userRoleRepository.save(usRole);
UserTbl userTbl = new UserTbl();
userTbl.setEmail("ganeshsagar58#gmail.com");
userTbl.setUsrPassword("c0b137fe2d792459f26ff763cce44574a5b5ab03");
userTbl.setFirstName("Ganesh");
userTbl.setLastName("Bhagavath");
UserRole userRole = userRoleRepository.findByUroName("Admin");
userTbl.setUro(userRole);
userRepository.save(userTbl);
}
};
}
}
Here is the UserTbl POJO
import java.math.BigInteger;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.joda.time.DateTime;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
#Document
public class UserTbl
{
#Id
private BigInteger id;
#DBRef
private UserRole uro;
#NotNull
#Size(min=2, max =30)
private String firstName;
#NotNull
#Size(min=2, max =30)
private String lastName;
#NotNull
#Email
private String email;
#NotNull
private String usrPassword;
private DateTime usrCreatedDttm;
private DateTime usrModifiedDttm;
public BigInteger getId() {
return id;
}
public void setId(BigInteger id) {
this.id = id;
}
public UserRole getUro() {
return uro;
}
public void setUro(UserRole uro) {
this.uro = uro;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getUsrPassword() {
return usrPassword;
}
public void setUsrPassword(String usrPassword) {
this.usrPassword = usrPassword;
}
public DateTime getUsrCreatedDttm() {
return usrCreatedDttm;
}
public void setUsrCreatedDttm(DateTime usrCreatedDttm) {
this.usrCreatedDttm = usrCreatedDttm;
}
public DateTime getUsrModifiedDttm() {
return usrModifiedDttm;
}
public void setUsrModifiedDttm(DateTime usrModifiedDttm) {
this.usrModifiedDttm = usrModifiedDttm;
}
}
Here is the UserRole POJO
import java.math.BigInteger;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document
public class UserRole
{
#Id
private BigInteger id;
private String uroName;
private String uroCode;
private String uroType;
private String uroCreatedDttm;
private String uroModifiedDttm;
public BigInteger getId() {
return id;
}
public void setId(BigInteger id) {
this.id = id;
}
public String getUroName() {
return uroName;
}
public void setUroName(String uroName) {
this.uroName = uroName;
}
public String getUroCode() {
return uroCode;
}
public void setUroCode(String uroCode) {
this.uroCode = uroCode;
}
public String getUroType() {
return uroType;
}
public void setUroType(String uroType) {
this.uroType = uroType;
}
public String getUroCreatedDttm() {
return uroCreatedDttm;
}
public void setUroCreatedDttm(String uroCreatedDttm) {
this.uroCreatedDttm = uroCreatedDttm;
}
public String getUroModifiedDttm() {
return uroModifiedDttm;
}
public void setUroModifiedDttm(String uroModifiedDttm) {
this.uroModifiedDttm = uroModifiedDttm;
}
}
Here is my Websecurity class
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
private UserRepository userRepository;
private BCryptPasswordEncoder bCryptPasswordEncoder;
private UserRoleRepository userRoleRepository;
#Autowired
public void setUserRoleRepository(UserRoleRepository userRoleRepository)
{
this.userRoleRepository = userRoleRepository;
}
#Autowired
public void setUserRepository(UserRepository userRepository)
{
this.userRepository = userRepository;
}
#Autowired
public void setbCryptPasswordEncoder(BCryptPasswordEncoder bCryptPasswordEncoder)
{
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
#Bean
public BCryptPasswordEncoder passwordEncoder(){
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
return bCryptPasswordEncoder;
}
#Bean
protected
UserDetailsService userDetailsService() {
return new UserDetailsService() {
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserTbl user = userRepository.findUserByEmail(username);
if (user != null) {
return new User(user.getEmail(), user.getUsrPassword(), true, true, true, true,
AuthorityUtils.createAuthorityList(userRoleRepository.findByUroName("Admin").getUroName()));
} else {
throw new UsernameNotFoundException("could not find the user '"
+ username + "'");
}
}
};
}
public void init(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(userDetailsService()).passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/posts/**", "/users/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
When i hit localhost:8080/login in POSTMAN with POST method (username and password as mentioned in UserTbl), it says
{
"timestamp": "2018-03-31T16:18:40.791+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/login"
}
My application.properties file
spring.data.mongodb.database=web_application
Please check once if you have defined different context explicitly in your application.properties file.
Spring Boot 1.X
server.contextPath=/yourAppContext
server.port=8080
Spring Boot 2.0
server.servlet.contextPath=/yourAppContext
If so, you would need to add context path to your request URL,
like ,
localhost:8080/yourAppContext/login
in my app I have controller:
package org.sample.web.config;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.sample.model.Contact;
import org.sample.model.Person;
import org.sample.model.PersonGender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import ch.ralscha.extdirectspring.generator.IncludeValidation;
import ch.ralscha.extdirectspring.generator.ModelGenerator;
import ch.ralscha.extdirectspring.generator.OutputFormat;
#Controller
#RequestMapping
public class ModelController {
private final Logger logger = LoggerFactory.getLogger(getClass());
#InitBinder
public void initBinder(WebDataBinder binder) {
logger.error("aaaaaaaaaaaaaaa");
binder.registerCustomEditor(PersonGender.class, new EnumPropertyEditor(PersonGender.class));
}
#RequestMapping("/app/model/Person.js")
public void user(HttpServletRequest request, HttpServletResponse response) throws IOException {
ModelGenerator.writeModel(request, response, Person.class, OutputFormat.EXTJS4, IncludeValidation.ALL, true);
}
#RequestMapping("/app/model/Contact.js")
public void catalog(HttpServletRequest request, HttpServletResponse response) throws IOException {
ModelGenerator.writeModel(request, response, Contact.class, OutputFormat.EXTJS4, IncludeValidation.ALL, true);
}
}
problem is that method with annotation InitBinder is never calling so when I want to validate my enut it throws exception:
javax.validation.UnexpectedTypeException: HV000030: No validator could be found for type: org.sample.model.PersonGender.
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.verifyResolveWasUnique(ConstraintValidatorManager.java:218)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.findMatchingValidatorClass(ConstraintValidatorManager.java:193)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.getInitializedValidator(ConstraintValidatorManager.java:97)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:125)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:91)
at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:85)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:478)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:424)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:388)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:340)
at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:158)
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:102)
at org.springframework.validation.DataBinder.validate(DataBinder.java:772)
EDIT:
PersonGender:
package org.sample.model;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
public enum PersonGender implements Serializable {
MALE("M"), FEMALE("F"), UNKNOWN("0");
private static final long serialVersionUID = 1L;
private static Map<String, PersonGender> identifierMap = new HashMap<String, PersonGender>();
static {
for (PersonGender value : PersonGender.values()) {
identifierMap.put(value.getValue(), value);
}
}
private String value;
private PersonGender(String value) {
this.value = value;
}
public static PersonGender fromValue(String value) {
PersonGender result = identifierMap.get(value);
if (result == null) {
throw new IllegalArgumentException("No PersonGender for value: " + value);
}
return result;
}
public String getValue() {
return value;
}
public String getName() {
return name();
}
}
EXCEPTIon occurs when submiting form:
#Service
public class SimpleService {
...
#ExtDirectMethod(value = ExtDirectMethodType.FORM_POST, group = "person")
public ExtDirectFormPostResult validatePersonForm(#Valid Person p, BindingResult result) {
if (!result.hasErrors()) {
// another validations
}
return new ExtDirectFormPostResult(result);
}
...
}