Return XML response Rest API with Spring - java

I am trying to response with XML to a given call to the API.
Right now it works with JSON, I can send JSON or XML and return JSON.
But I cannot do the same with XML.
From now what I have is this:
RestVoterController class:
#RequestMapping("/rest")
#RestController
public class RESTVoterController {
#Autowired
private VoterService voterService;
#RequestMapping(value = {"/user.json","/user"},
method = RequestMethod.POST,
consumes = {"application/json","application/xml"},
produces = {"application/json"})
#Transactional(readOnly = true)
public Voter getVoterInfoJSON(#RequestBody VoterRequestGet voterRequestGet) {
return this.voterService.findByEmailAndPassword(voterRequestGet.getLogin(), voterRequestGet.getPassword());
}
#RequestMapping(value = "/user.xml",
method = RequestMethod.POST,
consumes = {"application/xml","application/json"},
produces = "application/xml")
#Transactional(readOnly = true)
public Voter getVoterInfoXML(#RequestBody VoterRequestGet voterRequestGet) {
return this.voterService.findByEmailAndPassword(voterRequestGet.getLogin(), voterRequestGet.getPassword());
}
#RequestMapping(value = "/changepassword",
method = RequestMethod.POST,
headers = "Accept=application/json",
produces = "application/json")
#Transactional(readOnly = true)
public void changePassword(#RequestBody VoterRequestChangePassword voterRequestChangePassword) {
this.voterService.changePassword(voterRequestChangePassword.getLogin(), voterRequestChangePassword.getOldPassword(), voterRequestChangePassword.getNewPassword());
}
}
VoterRequestGet class:
#XmlRootElement(name = "user")
#XmlAccessorType(XmlAccessType.FIELD)
public class VoterRequestGet {
#XmlElement
private String login;
#XmlElement
private String password;
public VoterRequestGet()
{
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

I tested your code and it works for me. Please look:
First I create mock for voterService.
package com.example;
import org.springframework.stereotype.Service;
#Service
public class VoterService {
public Voter findByEmailAndPassword(String login, String password) {
Voter voter = new Voter();
voter.setLogin(login);
voter.setPassword(password);
return voter;
}
}
Then I have to slightly modify your controller (remove Transaction annotation because I have no data source in my service mock).
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RequestMapping("/rest")
#RestController
public class RESTVoterController {
#Autowired
private VoterService voterService;
#RequestMapping(value = {"/user.json","/user"},
method = RequestMethod.POST,
consumes = {"application/json","application/xml"},
produces = {"application/json"})
public Voter getVoterInfoJSON(#RequestBody VoterRequestGet voterRequestGet) {
return this.voterService.findByEmailAndPassword(voterRequestGet.getLogin(), voterRequestGet.getPassword());
}
#RequestMapping(value = "/user.xml",
method = RequestMethod.POST,
consumes = {"application/xml","application/json"},
produces = "application/xml")
public Voter getVoterInfoXML(#RequestBody VoterRequestGet voterRequestGet) {
return this.voterService.findByEmailAndPassword(voterRequestGet.getLogin(), voterRequestGet.getPassword());
}
}
Also I have to create mock for Voter because you don't share it.
package com.example;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "voter")
#XmlAccessorType(XmlAccessType.FIELD)
public class Voter {
#XmlElement
private String login;
#XmlElement
private String password;
public Voter() {
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public String toString() {
return "Voter [login=" + login + ", password=" + password + "]";
}
}
And finally integration test.
package com.example;
import javax.annotation.Resource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.WebIntegrationTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RestTemplate;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestApplication.class)
#WebIntegrationTest("server.port:0")
public class RESTVoterControllerTest {
private ServerProperties serverProperties;
private RestTemplate restTemplate = new RestTemplate();
#Resource
public void setServerProperties(ServerProperties serverProperties) {
this.serverProperties = serverProperties;
}
#Value("${local.server.port}")
private int serverPort;
private String serverUri;
#Before
public void setUp() throws Exception {
String contextPath = serverProperties.getContextPath();
serverUri = "http://localhost:" + serverPort + (contextPath == null ? "/" : contextPath);
}
#After
public void tearDown() throws Exception {
}
#Test
public void testCreate() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
VoterRequestGet voterRequest = new VoterRequestGet();
voterRequest.setLogin("email");
voterRequest.setPassword("secret");
HttpEntity<VoterRequestGet> request = new HttpEntity<>(voterRequest, headers);
System.out.println(restTemplate.postForEntity(
serverUri + "/rest/user.json", request, String.class).getBody());
System.out.println(restTemplate.postForEntity(
serverUri + "/rest/user.xml", request, String.class).getBody());
}
}
The result could be find in a output of the test and should contain two lines.
{"login":"email","password":"secret"}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><voter><login>email</login><password>secret</password></voter>

You need an XML mapping library like jackson, so adding this to your pom.xml will fix your problem:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>

produces = { MediaType.APPLICATION_JSON_VALUE}
is the solution to me

Related

'Field userRepository in com.userproject.Service.UserService required a bean named 'entityManagerFactory' that could not be found.'

This is User class, which serves as the Entity.
package com.userproject.Entities;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
#Entity
#Table(name = "userservice")
public class User {
#Id
#Column(name="userID")
int userId;
#Column(name="username")
String username;
#Column(name="age")
int age;
public User(int userId, String username, int age) {
super();
this.userId = userId;
this.username = username;
this.age = age;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
#Override
public String toString() {
return "User [userId=" + userId + ", username=" + username + ", age=" + age + "]";
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
This is my repository interface
package com.userproject.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import com.userproject.Entities.User;
public interface UserRepository extends JpaRepository<User, Integer> {
public User findById(int id);
}
This is my Service class
package com.userproject.Service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.userproject.Entities.User;
import com.userproject.dao.UserRepository;
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
public User addUser(User usr) {
User savedUser = this.userRepository.save(usr);
return savedUser;
}
public List<User> getAllInfo(){
Iterable<User> allUsers = this.userRepository.findAll();
return (List<User>)allUsers;
}
public User getUser(int usrId) {
User usr = this.userRepository.findById(usrId);
if (usr == null)
throw new NullPointerException();
return usr;
}
}
This is my Controller
package com.userproject.Controllers;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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;
import com.userproject.Entities.User;
import com.userproject.Service.UserService;
#RestController
#RequestMapping("/user")
public class UserController {
#Autowired
private UserService service;
#PostMapping("/add")
public ResponseEntity<User> addUser(#RequestBody User u){
try {
User addUser = this.service.addUser(u);
return ResponseEntity.ok(addUser);
} catch(Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
#GetMapping("/{id}")
public ResponseEntity<User> getUserById(#PathVariable("id") int userID){
try {
User u = this.service.getUser(userID);
return ResponseEntity.ok(u);
} catch(NullPointerException e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
#GetMapping("/all")
public ResponseEntity<List<User>> getAllUsers(){
try {
return ResponseEntity.ok(this.service.getAllInfo());
} catch(Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}
This is my main application class
package com.userproject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#EnableJpaRepositories("com.userproject.dao")
#SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class UserProjectApplication {
public static void main(String[] args) {
SpringApplication.run(UserProjectApplication.class, args);
}
}
This is application.properties file
spring.jpa.database=mysql
spring.datasource.username=*****
spring.datasource.password=*****
spring.datasource.url=jdbc:mysql://*******:3306/practice
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.jooq.sql-dialect = org.hibernate.dialect.MySQL57Dialect
spring.jpa.hibernate.ddl-auto= update
This is my project structure:
(https://i.stack.imgur.com/UR10B.png)
When I try to run the application, I keep getting the following message: `
Description:
Field userRepository in com.userproject.Service.UserService required a bean named 'entityManagerFactory' 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 named 'entityManagerFactory' in your configuration.
If I remove the "exclude" parameter from #SpringBootApplication, it throws an error stating the datasource cannot be configured as the url is missing.
If I remove the #EnableJpaRepositories, it throws an error stating my userRepository field in Service class cannot be configured.
From what I understand, this whole problem arises from me trying to autowire the userRepository field (which is actually an interface) in the Service class. However, SpringBoot shall be able to do that with the help of proxy classes.
Please provide me with a solution to this.

Spring-Data Project is not receiving my Get/Post "404 not found"

I finished creating a simple Spring-boot project in which I can enter users and through the Get command it returns me the name (from a list of identical names) with the oldest entry date. Unfortunately, every time I ask for Get it returns this ERROR:
D:\>curl -G localhost:8080/demo/first?=Biagio
{"timestamp":"2020-10-04T22:46:35.996+00:00","status":404,"error":"Not Found","message":"","path":"/demo/first"}
And to each of my POST / Add requests like this ERROR:
D:\>curl localhost:8080/demo/add -d name=Giovanni -d email=giovanni#gmail.com -d surname=Jackie
{"timestamp":"2020-10-04T22:40:51.928+00:00","status":404,"error":"Not Found","message":"","path":"/demo/add"}
Below I enter the interested parties of my project to try to get something out of it, because I have been stuck for days now
AccessingDataMysqlApplication.java
package com.example.accessingdatamysql;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class AccessingDataMysqlApplication {
public static void main(String[] args) {
SpringApplication.run(AccessingDataMysqlApplication.class, args);
}
}
MainController.java
package com.example.accessingdatamysql.rest;
import javax.persistence.NoResultException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.example.accessingdatamysql.model.UserDto;
import com.example.accessingdatamysql.service.UserService;
#RestController
#RequestMapping("/demo")
public class MainController {
#Autowired
private UserService userService;
#Transactional
//#RequestMapping(value = "/add/", method = RequestMethod.POST)
#PostMapping(path="/demo/add")
public String addNewUser(#PathVariable("name") String name, #PathVariable("email") String email,
#PathVariable("surname") String surname) {
UserDto n = new UserDto();
n.setName(name);
n.setSurname(surname);
n.setEmail(email);
userService.create(n);
return "User Saved in DB";
}
#SuppressWarnings({ "rawtypes", "unchecked" })
//#RequestMapping(value = "/fetchUser/{name}", method = RequestMethod.GET)
#GetMapping("/demo/first")
public ResponseEntity<UserDto> fetchUser(#PathVariable("name") String name) {
System.out.println(name);
try {
UserDto namefound = userService.findFirstByName(name);
System.out.println("Name found");
ResponseEntity<UserDto> user = new ResponseEntity<UserDto>(namefound, HttpStatus.OK);
return user;
} catch(NoResultException ne) {
System.out.println("User not found");
return new ResponseEntity("User not found with name : " + name, HttpStatus.NOT_FOUND);
}
}
}
UserService.java
package com.example.accessingdatamysql.service;
import org.springframework.stereotype.Service;
import com.example.accessingdatamysql.model.UserDto;
#Service
public interface UserService {
UserDto findFirstByName(String name);
void create(UserDto user);
}
UserServiceImpl.java
package com.example.accessingdatamysql.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import com.example.accessingdatamysql.model.UserDto;
import com.example.accessingdatamysql.model.UserEntity;
import com.example.accessingdatamysql.repo.UserRepository;
import com.example.accessingdatamysql.util.UserMapper;
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository userRepository;
#Autowired
UserMapper mapper;
#Override
public UserDto findFirstByName(String name) {
UserEntity entity = userRepository.findFirstByName(name);
return mapper.toDtoMapper(entity);
}
#Override
public void create(UserDto user) {
UserEntity entity = mapper.toEntityMapper(user);
userRepository.create(entity);
}
}
UserMapper.java
package com.example.accessingdatamysql.util;
import org.mapstruct.Mapper;
import com.example.accessingdatamysql.model.UserDto;
import com.example.accessingdatamysql.model.UserEntity;
#Mapper(componentModel = "spring")
public interface UserMapper {
public UserEntity toEntityMapper (UserDto user);
public UserDto toDtoMapper (UserEntity userEntity);
}
UserRepository.java
package com.example.accessingdatamysql.repo;
import org.springframework.stereotype.Repository;
import com.example.accessingdatamysql.model.UserEntity;
#Repository
public interface UserRepository {
UserEntity findFirstByName(String name);
void create(UserEntity entity);
}
UserRepositoryImpl.java
package com.example.accessingdatamysql.service;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.springframework.stereotype.Component;
import com.example.accessingdatamysql.model.UserEntity;
import com.example.accessingdatamysql.repo.UserRepository;
#Component
public class UserRepositoryImpl implements UserRepository {
private final EntityManager em;
public UserRepositoryImpl(EntityManager entityManager) {
this.em = entityManager;
}
#Override
public UserEntity findFirstByName(String name) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<UserEntity> criteria = builder.createQuery(UserEntity.class);
Root<UserEntity> root = criteria.from(UserEntity.class);
criteria.select(root).where(builder.equal(root.get("name"), name));
criteria.orderBy(builder.asc(root.get("timestamp")));
TypedQuery<UserEntity> query = em.createQuery(criteria).setMaxResults(1);
return query.getSingleResult();
}
#Override
// per la creazione//
public void create(UserEntity entity) {
em.persist(entity);
}
}
UserDto.java
package com.example.accessingdatamysql.model;
import java.io.Serializable;
import java.sql.Timestamp;
public class UserDto implements Serializable {
/**
*
*/
private static final long serialVersionUID = -7621330660870602403L;
/**
*
*/
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Timestamp getTimestamp() {
return timestamp;
}
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
private Timestamp timestamp;
private String email;
private String surname;
}
If you need I can also insert User.java and the pom, but the pom has no problems as the dependencies are all correct.
You have an additional demo in your path descriptions for GET and POST methods, you should remove it:
#GetMapping("/demo/first")
#PostMapping(path = "/demo/first")
It should be :
#GetMapping("/first")
#PostMapping(path = "/first")
This because you have already defined demo in the RequestMapping annotation in the class level.

How to parse request parameter (query and path param) and request body in same POJO in REST API

I have a rest API (PUT verb) which accepts both request body and path params:
Ex:
curl --data {a:1, b:2} -X PUT "https://example.com/users/{username}/address/{addressname}"
I am trying to fetch both request body and path param in one POJO
Response myAPI(#BeanParam Users user){
system.out.println(user.username);
system.out.println(user.a);
Users class
public class Users{
#PathParam(username)
private String userName;
......
private String a;
......
}
But I am getting value of user.a as null.
How to parse both request body and param in same class?
You can do this with a custom annotation and an InjectionResolver. What the InjectionResolver does is allow you to create a custom injection point with your own annotation. So you could do something like
public class Users {
#PathParam(username)
private String userName;
#Body
private String a;
}
When implementing the InjectionResolver, you would grab the actual body from the ContainerRequest using the ContainerRequest#readEntity(Class) method. You would determine the Class to pass by doing some reflection on the Field that you can obtain inside the InjectionResolver. Below is a complete example using Jersey Test Framework. Run it like any other JUnit test.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.BeanParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import org.glassfish.hk2.api.Injectee;
import org.glassfish.hk2.api.InjectionResolver;
import org.glassfish.hk2.api.ServiceHandle;
import org.glassfish.hk2.api.TypeLiteral;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
/**
* Only one required dependency to run this test. Note this is using 2.25.1.
* If you are using 2.26 or later, the implementation will be different,
* and this will not work. You need to use the Jersey packaged `InjectionResolver`,
* not the HK2 one. And you will also need to bind that `InjectionResolver`
* to `GenericType` instead of `TypeLiteral` in the `AbstractBinder#configure()`.
*
* <dependency>
* <groupId>org.glassfish.jersey.test-framework.providers</groupId>
* <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
* <version>2.25.1</version>
* <scope>test</scope>
* </dependency>
*/
public class BeanParamTest extends JerseyTest {
#Path("test")
#Consumes("application/json")
#Produces("application/json")
public static class TestResource {
#POST
#Path("{username}")
public String post(#BeanParam ModelBean bean) {
return bean.toString();
}
}
#Override
public ResourceConfig configure() {
return new ResourceConfig(TestResource.class)
.register(new AbstractBinder() {
#Override
protected void configure() {
bind(BodyInjectionResolver.class)
.to(new TypeLiteral<InjectionResolver<Body>>() {})
.in(Singleton.class);
}
});
}
#Test
public void testIt() {
final Response res = target("test/peeskillet")
.request()
.post(Entity.json("{\"foo\":\"bar\"}"));
System.out.println(res.readEntity(String.class));
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD})
public #interface Body {}
public static class ModelBean {
#PathParam("username")
private String username;
#Body
private String body;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
#Override
public String toString() {
return "ModelBean{" +
"username='" + username + '\'' +
", body='" + body + '\'' +
'}';
}
}
public static class BodyInjectionResolver implements InjectionResolver<Body> {
#Inject
private javax.inject.Provider<ContainerRequest> requestProvider;
#Override
public Object resolve(Injectee injectee, ServiceHandle<?> serviceHandle) {
if (injectee.getParent().isAnnotationPresent(Body.class)) {
AnnotatedElement parent = injectee.getParent();
if (parent instanceof Field) {
Class<?> entityType = ((Field) parent).getType();
return requestProvider.get().readEntity(entityType);
}
}
return null;
}
#Override
public boolean isConstructorParameterIndicator() {
return false;
}
#Override
public boolean isMethodParameterIndicator() {
return false;
}
}
}

Jersey client unable to convert ArrayList to xml

I have developed one restful webservice using jersey and spring.
Below is the service method which servers the request by accepting the list of Login objects.
Method in service class
#POST
#Path(value = "/login")
#Produces(MediaType.APPLICATION_XML)
public String getLogin(Login login);
#POST
#Path(value = "/update")
#Consumes(MediaType.APPLICATION_XML)
public void updatePassword(List<Login> userList)
Login class
#XmlRootElement
public class Login {
//some code
}
I am using the jersey client to consume this webservice as below.
loginList = ArrayList of Login objects
Client client = Client.create();
WebResource webResource = client.resource("http://localhost:8080/user/update");
ClientResponse response = webResource.accept(MediaType.APPLICATION_XML).type(MediaType.APPLICATION_XML).post(ClientResponse.class, loginList);
But below is the exception which I am getting.
Caused by: com.sun.jersey.api.client.ClientHandlerException: A message body writer for Java type, class java.util.ArrayList, and MIME media type, application/xml, was not found
at com.sun.jersey.api.client.RequestWriter.writeRequestEntity(RequestWriter.java:288)
at com.sun.jersey.client.urlconnection.URLConnectionClientHandler._invoke(URLConnectionClientHandler.java:204)
at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:147)
But My /login i.e. getLogin method works perfectly.
I am not able to figure out what exactly is causing this issue.
Can anyone please help me what could be the wrong happening in this.
Thanks in advance.
I guess you need to use GenericEntity for generic types, because of type erasure. And JAXB needs to know the type. The GenericEntity stores the type through it parameter. So basically, you just need to do
.post(ClientResponse.class, new GenericEntity<List<Login>>(list){});
UPDATE
complete test using Jersey Test Framework
<dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-grizzly2</artifactId>
<version>1.19</version>
<scope>test</scope>
</dependency>
Login
#XmlRootElement
public class Login {
private String name;
private String password;
public Login() {
}
public Login(String name, String password) {
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public String toString() {
return "Login{" + "name=" + name + ", password=" + password + '}';
}
}
Test
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.core.DefaultResourceConfig;
import com.sun.jersey.spi.container.servlet.WebComponent;
import com.sun.jersey.test.framework.JerseyTest;
import com.sun.jersey.test.framework.WebAppDescriptor;
import com.sun.jersey.test.framework.spi.container.TestContainerFactory;
import com.sun.jersey.test.framework.spi.container.grizzly2.web.GrizzlyWebTestContainerFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import org.junit.Test;
public class ArrayTest extends JerseyTest {
#Path("/login")
public static class LoginResource {
#POST
#Consumes(MediaType.APPLICATION_XML)
public String post(List<Login> logins) {
return new HashSet<>(logins).toString();
}
}
public static class AppConfig extends DefaultResourceConfig {
public AppConfig() {
super(LoginResource.class);
}
}
#Override
public TestContainerFactory getTestContainerFactory() {
return new GrizzlyWebTestContainerFactory();
}
#Override
public WebAppDescriptor configure() {
return new WebAppDescriptor.Builder()
.initParam(WebComponent.RESOURCE_CONFIG_CLASS,
AppConfig.class.getName())
.build();
}
#Test
public void doTest() {
List<Login> list = new ArrayList<>();
list.add(new Login("pee", "skillet"));
ClientResponse response = resource().path("login")
.type(MediaType.APPLICATION_XML)
.post(ClientResponse.class, new GenericEntity<List<Login>>(list){});
System.out.println("Status " + response.getStatus());
System.out.println(response.getEntity(String.class));
}
}
If you remove the GenericEntity, you will get the error.

Spring MVC error

I'm pretty much completely new to the world of computer programming, so it's been something of a struggle getting a really in depth understanding of many concepts. Right now, I'm working on a project in which we are implementing Spring MVC. The first step in the project is to make a login page for a website. I've tried modelling mine after one that we did in class, but I can't seem to get past the following error in my web browser:
Unsupported auto value type java.lang.String for field injuryReports.Login.userName
Here is my Login entity class:
package injuryReports;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class Login implements Serializable {
private static final long serialVersionUID = 1L;
#Id #GeneratedValue
private String userName;
private String password;
private int userId;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public Login() {
}
public Login(String userName, String password) {
super();
this.userName = userName;
this.password = password;
}
public Login(int userId, String userName2, String password2) {
this.userId = userId;
this.userName = userName2;
this.password = password2;
}
}
My LoginDao Class:
package injuryReports;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
*
* #author nGent
*
*/
#Component
public class LoginDao {
#PersistenceContext private EntityManager em;
#Transactional
public void persist(Login user) {
em.persist(user);
}
public List<Login> getAllUsers() {
TypedQuery<Login> query = em.createQuery(
"Select u FROM Login u ORDER BY u.id", Login.class);
return query.getResultList();
}
public Login validateLogin(String userName, String password) {
Login login = null;
TypedQuery<Login> query = em.createQuery(
"Select u From Login u where u.userName = :userName " +
" and u.password = :password", Login.class).setParameter(
"userName", userName).setParameter("password", password);
try {
login = query.getSingleResult();
}
catch (Exception e) {
//TODO: Handle Exception
}
return login;
}
}
And my LoginController class:
package injuryReports;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class LoginController {
#Autowired
private LoginDao loginDao;
#RequestMapping(value = "/user", method = {RequestMethod.POST})
public ModelAndView userEntry(HttpServletRequest request) {
String userName = request.getParameter("userName");
String password = request.getParameter("password");
if (userName != "" && password != "") {
loginDao.persist(new Login(userName, password));
}
return new ModelAndView("logon.jsp", "loginDao", loginDao);
}
#RequestMapping(value = "/login")
public ModelAndView login(HttpServletRequest request) {
String userName = request.getParameter("userName");
String password = request.getParameter("password");
String page = "login.jsp";
if (userName != "" && password != "") {
try {
Login login = loginDao.validateLogin(userName, password);
if (login != null) {
request.getSession().setAttribute("UserId", login.getUserId());
page = "login.jsp";
}
}
catch (Exception e) {
//TODO: Handle Exception
}
}
return new ModelAndView(page, getDaos());
}
#RequestMapping(value = "/logon", method = {RequestMethod.GET})
public ModelAndView logon(HttpServletRequest request) {
//int userId = (Integer) request.getSession().getAttribute("userId");
//request.getSession().setAttribute("UserID", userId);
return new ModelAndView("logon.jsp", getDaos());
}
public Map<String, Object> getDaos() {
Map<String, Object> models = new HashMap<String, Object>();
models.put("loginDao", loginDao);
return models;
}
}
Sorry this is a bit long- I wanted to provide as much information as possible. I'd really appreciate any help!
You cannot use #GeneratedValue on String property. It uses database sequences or AUTOINCREMENT features depending on the underlying database engine.
Either remove this annotation:
#Id
private String userName;
or use integer/long for id:
#Id #GeneratedValue
private int userId;

Categories