簡體   English   中英

我的REST API(使用Jersey)無法找到持久實體(使用OpenJPA)的消息正文編寫器(用於JSON)。

[英]My REST API (using Jersey) cannot find a message body writer (for JSON) for a persisted entity (using OpenJPA).

我正在訪問MySql數據庫的服務器上實現REST API。 使用JDBC / OpenJPA訪問該數據庫。 有幾種對象模型都帶有OpenJPA批注(@ Id,@ Column等)和對象XML綁定批注(@ XmlRootElement,@ XmlElement等)。 我正在將Jersey用於REST API。 問題是,當嘗試訪問“ 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有消息正文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當“ 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 但是,當我重寫“ myapp /.../ users / admin”的函數以創建新的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>

相關堆棧跟蹤:

Oct 20, 2014 11:30:48 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive /var/lib/tomcat7/webapps/stod.war
Oct 20, 2014 11:30:50 AM org.apache.catalina.startup.TaglibUriRule body
INFO: TLD skipped. URI: urn:com:sun:jersey:api:view is already defined
Oct 20, 2014 11:30:51 AM com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
  com.stod.server
Oct 20, 2014 11:30:51 AM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
  class com.stod.server.Service
Oct 20, 2014 11:30:51 AM com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
Oct 20, 2014 11:30:51 AM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.17.1 02/28/2013 03:28 PM'
Oct 20, 2014 11:30:56 AM com.sun.jersey.spi.container.ContainerResponse write
SEVERE: A message body writer for 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
Oct 20, 2014 11:30:56 AM com.sun.jersey.spi.container.ContainerResponse write
SEVERE: The registered message body writers compatible with the MIME media type are:
application/json ->
  com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$App
  com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$App
  com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$App
*/* ->
  com.sun.jersey.core.impl.provider.entity.FormProvider
  com.sun.jersey.core.impl.provider.entity.StringProvider
  com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
  com.sun.jersey.core.impl.provider.entity.FileProvider
  com.sun.jersey.core.impl.provider.entity.InputStreamProvider
  com.sun.jersey.core.impl.provider.entity.DataSourceProvider
  com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.ReaderProvider
  com.sun.jersey.core.impl.provider.entity.DocumentProvider
  com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider
  com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter
  com.sun.jersey.server.impl.template.ViewableMessageBodyWriter
  com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General

Oct 20, 2014 11:30:56 AM com.sun.jersey.spi.container.ContainerResponse logException
SEVERE: Mapped exception to response: 500 (Internal Server Error)
javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: A message body writer for 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
    at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:285)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1479)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1391)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1381)
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:716)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.sun.jersey.api.MessageException: A message body writer for 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
    ... 24 more

Exception stacktrace表示,沒有MessageBodyWriter:

javax.ws.rs.WebApplicationException:com.sun.jersey.api.MessageException:Java類org.apache.openjpa.enhance.com $ stod $ models $ User $ pcsubclass和Java類型類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類型類com.stod.models.User和MIME媒體類型application / json


對我來說,您的轉換用戶的運行時類型似乎不匹配,並且jersey無法找到正確的類來創建新實例。 但是我不是100%肯定,所以不要怪我 ;)

如果您從lHelper.findUser(user)找回了用戶,請確保該用戶確實屬於用戶類型。 看起來它有點像是一個openjpa代理,它不是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)類的單一類型會更好(在代碼方面@XmlAccessorType(XmlAccessType.FIELD) ,在這種情況下,僅注釋字段聲明-但使用nvm;)

希望這對您有所幫助/祝您有個愉快的一天。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM