找不到媒体类型=application/xml、类型=class java.util.HashMap$Values 的 MessageBodyWriter
MessageBodyWriter not found for media type=application/xml, type=class java.util.HashMap$Values
我的 API 方法无法将对象转换为 XML,但它可以转换为 JSON。当方法 return 类型是 Collection (MAP) 时,它会转换为 XML 而不会出现任何运行时异常(未找到 MessageBodyWriter),但是当使用 Response 作为 return 类型时,它会导致运行时异常。在这里我提到代码。我认为我的代码没有任何问题,但依赖项有问题。
package lk.ac.jfn.vau.MyDBapi.Model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Department {
private long Id;
private String Name;
private String Location;
public Department() {
}
public Department(long id, String name, String location) {
super();
Id = id;
Name = name;
Location = location;
}
public long getId() {
return Id;
}
public void setId(long id) {
Id = id;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getLocation() {
return Location;
}
public void setLocation(String location) {
Location = location;
}
}
package lk.ac.jfn.vau.MyDBapi.Repo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Repo {
private static final String DB_Driver = "com.mysql.jdbc.Driver";
private static final String DB_Connection = "jdbc:mysql://localhost:3306/";
private static final String DB_Name = "departmentapi";
private static final String DB_User = "root";
private static final String DB_Password = "";
public static void getDriver() {
try {
Class.forName(DB_Driver);
System.out.println("Driver found");
} catch (ClassNotFoundException e) {
System.out.println("Driver not found " + e.getMessage());
}
}
public static Connection getConnection() {
Connection connection = null;
try {
connection = DriverManager.getConnection(DB_Connection + DB_Name, DB_User, DB_Password);
System.out.println("Database Connected");
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return connection;
}
public ResultSet get(String query, Connection connection) {
ResultSet resultSet = null;
try {
Statement statement = connection.createStatement();
resultSet = statement.executeQuery(query);
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return resultSet;
}
}
package lk.ac.jfn.vau.MyDBapi.Repo;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import lk.ac.jfn.vau.MyDBapi.Model.Department;
public class DepartmentRepo extends Repo {
Connection connection=null;
public DepartmentRepo() {
getDriver();
connection = getConnection();
}
Map<Long, Department>map=new HashMap<Long, Department>();
public Collection<Department> getAll(){
ResultSet resultSet=get("select * from department", connection);
try {
while(resultSet.next()) {
Department department=new Department(resultSet.getLong(1), resultSet.getString(2), resultSet.getString(3));
map.put(department.getId(), department);
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return map.values();
}
}
package lk.ac.jfn.vau.MyDBapi;
import java.util.Collection;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import lk.ac.jfn.vau.MyDBapi.Model.Department;
import lk.ac.jfn.vau.MyDBapi.Repo.DepartmentRepo;
@Path("/dept")
@Produces(value = {MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
@Consumes(MediaType.APPLICATION_JSON)
public class DepartmentResource {
private DepartmentRepo repo=new DepartmentRepo();
@GET
public Response getDepartments() {
Collection<Department> departments = repo.getAll();
if(!departments.isEmpty()) {
return Response.status(Status.FOUND).entity(departments).build();
}
return Response.status(Status.NOT_FOUND).entity("Nothing Found").build();
}
}
POM.xml
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
</dependencies>
使用 JAXB(XML 提供程序),您需要使用 GenericEntity
。
GenericEntity<Collection<Department>> entity
= new GenericEntity<Collection<Department>>(departments){};
return Response.ok(entity).build();
您需要这样做的原因是 JAXB 需要知道类型信息才能序列化。当你只是 return 泛型实体时,而不是 Response
,泛型类型信息在方法签名中
@GET
public Collection<Department> getDepartments() {}
当您使用 Response
时,由于类型擦除,通用信息不可用。所以 JAX-RS 允许的是使用 GenericEntity
。但是你不能只使用一个实例,因为类型擦除不允许这样做。您实际上需要使用匿名 class
new GenericEntity<Collection<Department>>(departments){}
注意最后的大括号。这是一个匿名 class。通过反射,你可以从这个匿名class.
中得到泛型类型参数
我的 API 方法无法将对象转换为 XML,但它可以转换为 JSON。当方法 return 类型是 Collection (MAP) 时,它会转换为 XML 而不会出现任何运行时异常(未找到 MessageBodyWriter),但是当使用 Response 作为 return 类型时,它会导致运行时异常。在这里我提到代码。我认为我的代码没有任何问题,但依赖项有问题。
package lk.ac.jfn.vau.MyDBapi.Model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Department {
private long Id;
private String Name;
private String Location;
public Department() {
}
public Department(long id, String name, String location) {
super();
Id = id;
Name = name;
Location = location;
}
public long getId() {
return Id;
}
public void setId(long id) {
Id = id;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getLocation() {
return Location;
}
public void setLocation(String location) {
Location = location;
}
}
package lk.ac.jfn.vau.MyDBapi.Repo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Repo {
private static final String DB_Driver = "com.mysql.jdbc.Driver";
private static final String DB_Connection = "jdbc:mysql://localhost:3306/";
private static final String DB_Name = "departmentapi";
private static final String DB_User = "root";
private static final String DB_Password = "";
public static void getDriver() {
try {
Class.forName(DB_Driver);
System.out.println("Driver found");
} catch (ClassNotFoundException e) {
System.out.println("Driver not found " + e.getMessage());
}
}
public static Connection getConnection() {
Connection connection = null;
try {
connection = DriverManager.getConnection(DB_Connection + DB_Name, DB_User, DB_Password);
System.out.println("Database Connected");
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return connection;
}
public ResultSet get(String query, Connection connection) {
ResultSet resultSet = null;
try {
Statement statement = connection.createStatement();
resultSet = statement.executeQuery(query);
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return resultSet;
}
}
package lk.ac.jfn.vau.MyDBapi.Repo;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import lk.ac.jfn.vau.MyDBapi.Model.Department;
public class DepartmentRepo extends Repo {
Connection connection=null;
public DepartmentRepo() {
getDriver();
connection = getConnection();
}
Map<Long, Department>map=new HashMap<Long, Department>();
public Collection<Department> getAll(){
ResultSet resultSet=get("select * from department", connection);
try {
while(resultSet.next()) {
Department department=new Department(resultSet.getLong(1), resultSet.getString(2), resultSet.getString(3));
map.put(department.getId(), department);
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return map.values();
}
}
package lk.ac.jfn.vau.MyDBapi;
import java.util.Collection;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import lk.ac.jfn.vau.MyDBapi.Model.Department;
import lk.ac.jfn.vau.MyDBapi.Repo.DepartmentRepo;
@Path("/dept")
@Produces(value = {MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
@Consumes(MediaType.APPLICATION_JSON)
public class DepartmentResource {
private DepartmentRepo repo=new DepartmentRepo();
@GET
public Response getDepartments() {
Collection<Department> departments = repo.getAll();
if(!departments.isEmpty()) {
return Response.status(Status.FOUND).entity(departments).build();
}
return Response.status(Status.NOT_FOUND).entity("Nothing Found").build();
}
}
POM.xml
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
</dependencies>
使用 JAXB(XML 提供程序),您需要使用 GenericEntity
。
GenericEntity<Collection<Department>> entity
= new GenericEntity<Collection<Department>>(departments){};
return Response.ok(entity).build();
您需要这样做的原因是 JAXB 需要知道类型信息才能序列化。当你只是 return 泛型实体时,而不是 Response
,泛型类型信息在方法签名中
@GET
public Collection<Department> getDepartments() {}
当您使用 Response
时,由于类型擦除,通用信息不可用。所以 JAX-RS 允许的是使用 GenericEntity
。但是你不能只使用一个实例,因为类型擦除不允许这样做。您实际上需要使用匿名 class
new GenericEntity<Collection<Department>>(departments){}
注意最后的大括号。这是一个匿名 class。通过反射,你可以从这个匿名class.
中得到泛型类型参数