我的REST API(使用Jersey)无法为持久化实体(使用OpenJPA)找到消息正文编写器(对于JSON)。

时间:2014-10-20 16:10:30

标签: java json rest jersey openjpa

我在访问MySql数据库的服务器上实现REST API。使用JDBC / OpenJPA访问数据库。有几个对象模型使用OpenJPA注释(@ Id,@ Column等)和对象XML绑定注释(@XmlRootElement,@ XMLElement等)进行注释。我使用Jersey作为REST API。问题是,当尝试访问类似" myapp /.../ users / admin"我收到一条错误消息,指出{" myapp /.../ users / admin"读取数据库。但是当我重写" myapp /.../ users / admin"的功能时要创建一个新的Java class org.apache.openjpa.enhance.com$stod$models$User$pcsubclass, and Java type class com.stod.models.User, and MIME media type application/json was not found对象(不先持久保存到数据库),一切都按预期工作。为什么?

以下是相关的代码段。

com.stod.models.User

User.class

@XmlRootElement(name = "user") @XmlAccessorType(XmlAccessType.NONE) @Entity(name = "USER") public class User implements Base, Serializable { private static final long serialVersionUID = 8015178615266549325L; @Id @Column(name = "USERNAME", nullable = false, length = 128, unique = true, updatable = false) private String username; @Column(name = "PASSWORDHASH", nullable = false, length = 128, unique = false, updatable = true) private String passwordHash; @OneToMany(mappedBy = "owner", cascade = { CascadeType.MERGE, CascadeType.PERSIST }) private Collection<Circle> circlesOwned; @XmlElement public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @XmlTransient public String getPasswordHash() { return passwordHash; } public void setPasswordHash(String password) { this.passwordHash = DigestUtils.sha256Hex(password); } @XmlElement public Collection<Circle> getCirclesOwned() { return circlesOwned; } public void setCirclesOwned(Collection<Circle> circlesOwned) { this.circlesOwned = circlesOwned; } //... }

Circle.class

@XmlRootElement(name = "circle") @XmlAccessorType(XmlAccessType.NONE) @Entity(name = "CIRCLE") public class Circle implements Base, Serializable { private static final long serialVersionUID = 4653602066511306690L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "CIRCLEID") @XmlElement private Integer id; @Column(name = "NAME", nullable = false, length = 128, unique = false, updatable = true) private String name; @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST }) @XmlInverseReference(mappedBy="circlesOwned") private User owner; }

Service.class

@Path("/service") public class Service { static HighLogicHelper lHelper = null; static { if (lHelper == null) { try { lHelper = new HighLogicHelper(); } catch (Exception e) { e.printStackTrace(); } } } @GET @Path("/hello") @Produces("text/plain") public String hello() { return "Hello World"; } @GET @Path("/echo/{message}") @Produces("text/plain") public String echo(@PathParam("message") String message) { return message + " is your message"; } @GET @Path("/users/{username}") @Produces("application/json") public User getUser(@PathParam("username") String username) { User user = new User(); user.setUsername(username); user = (User) lHelper.findUser(user); //lHelper finds the user by username and returns the persisted object off the database User user2 = new User(); user2.setUsername(user.getUsername()); user2.setCirclesOwned(user.getCirclesOwned()); //NOTE! returning user2 works just fine (because user2 wasn't previously persisted?) return user; } }

web.xml

完整<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>com.vogella.jersey.first</display-name> <servlet> <servlet-name>Jersey REST Service</servlet-name> <servlet-class> com.sun.jersey.spi.container.servlet.ServletContainer </servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>com.stod.server</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey REST Service</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> </web-app>

pom.xml

相关堆栈跟踪:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.stod.server</groupId>
    <artifactId>stod-server</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>

    <name>stod-server</name>
    <url>http://maven.apache.org</url>

    <dependencies>
        <dependency>
            <groupId>com.stod.models</groupId>
            <artifactId>stod-models</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <scope>compile</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <!-- <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxrs</artifactId> 
            <version>2.0.0.GA</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> 
            <artifactId>resteasy-jaxb-provider</artifactId> <version>1.1.GA</version> 
            </dependency> -->
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.17.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-servlet</artifactId>
            <version>1.12</version>
            <scope>runtime</scope>
        </dependency>


        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-bundle</artifactId>
            <version>1.17.1</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.1</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <url>http://localhost:8080/manager/text</url>
                    <server>TomcatServer</server>
                    <path>/stod</path>
                    <update>true</update>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

1 个答案:

答案 0 :(得分:0)

Exception stacktrace说,没有MessageBodyWriter:

  

javax.ws.rs.WebApplicationException:com.sun.jersey.api.MessageException:Java类的消息体编写器org.apache.openjpa.enhance.com $ stod $ models $ User $ pcsubclass和Java类class com.stod.models.User,找不到MIME媒体类型application / json

,尤其不适用于org.apache.openjpa.enhance.com $ stod $ models $ User $ pcsubclass:

  

org.apache.openjpa.enhance.com $ stod $ models $ User $ pcsubclass,Java type class com.stod.models.User,找不到MIME媒体类型application / json


对我来说,看起来你的演员用户的运行时类型不匹配,并且jersey无法找到正确的类来创建新的实例。 (但我不是百分百肯定所以不要怪我;))

如果您从lHelper.findUser(user)取回用户,请确保用户确实属于用户类型。看起来它是一个openjpa代理some-what,它不是XMLRootElement,因此代码不起作用......

混合球衣版本,这是不行的:

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-server</artifactId>
    <version>1.17.1</version> <-----------------------------
</dependency>

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-servlet</artifactId>
    <version>1.12</version> <-------------------------------
    <scope>runtime</scope>
</dependency>

然后,有更新的版本,想想你的升级球衣项目。目前新的2.13对我来说在生产中运行良好。

顺便说一下,你混合了XmlAccessorTypes。在我看来,使用像@XmlAccessorType(XmlAccessType.FIELD)这样的单一类型更好(代码方式),在这种情况下只注释字段声明 - 但是nvm;)

希望这在某种程度上有所帮助/有美好的一天。