2016-10-04 23 views
2

Jerseyを使用してREST APIを作成するJavaで動的Webプロジェクト(ローカルアプリケーションサーバーTomcat 7にデプロイされています)があります。Jerseyで本体要求のPOST JSON

私はビルドの自動化ツールを使用しません(したがって、私のライブラリはビルドパスに追加され、サーブレットは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_2_5.xsd" id="WebApp_ID" version="2.5"> 
    <display-name>UserAccount</display-name> 
    <servlet> 
     <servlet-name>ServletAdaptor</servlet-name> 
     <servlet-class>com.sun.jersey.server.impl.container.servlet.ServletAdaptor</servlet-class> 
     <init-param> 
      <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> 
      <param-value>true</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>ServletAdaptor</servlet-name> 
     <url-pattern>/rest/*</url-pattern> 
    </servlet-mapping> 
</web-app> 

アプリケーションがMySQLデータベースと対話している:

asm-3.1.jar 
gson-2.2.1.jar 
jersey-client-1.0.3.jar 
jersey-core-1.0.3.jar 
jersey-json-1.18.jar 
jersey-server-1.0.3.jar 
jettison-1.1.jar 
jsr311-api-1.0.jar 
mysql-connector-java-5.0.8-bin.jar 

私のweb.xmlファイルは以下の通りです。 シナリオは次のとおりです。データベースには、ユーザーというユーザーアカウントテーブルがあります。列には、ID、名前、ユーザー名、パスワードが入ります。

アカウント(ユーザー名+パスワード)が有効かどうかを確認するPOSTメソッドがあります。 (ユーザー名とパスワードヘッダーのparamsとして渡された) http://localhost:8080/UserAccount/rest/login/doLogin やヘッダ: ユーザー名:X パスワード:1234

@POST 
@Path("/doLogin") 
@Produces(MediaType.APPLICATION_JSON) 
public String doLogin(@HeaderParam("username") String uname, @HeaderParam("password") String pwd){ 
    String response = ""; 
    if(checkCredentials(uname, pwd)){ 
     response = Utility.constructJSON("login",true); 
    }else{ 
     response = Utility.constructJSON("login", false, "Incorrect Email or Password"); 
    } 
return response;   
} 

あなたが見ることができるように、応答があれば基づき、真または偽でJSONを生成しますユーザーアカウントが有効かどうか。 これまでは正常に動作しています。 GETを実行し、パラメータをクエリのパラメータとして渡しても問題ありません(ただし、それは重要ではありません)。

は今、私はPOSTをやろうとしていますが、今回はJSONボディにユーザ名とパスワードを渡す:User.javaというクラスを作成しているIこのため

{ 
    "username":"x", 
    "password":"1234" 
} 

@XmlRootElement() 
@XmlAccessorType(XmlAccessType.FIELD) 
public class User implements Serializable { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 

    @XmlElement(name="username") 
    private String username; 

    @XmlElement(name="password") 
    private String password; 

    public String getUsername() { 
     return username; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    @Override 
    public String toString() { 
     // TODO Auto-generated method stub 
     return "username: " + username; 
    } 
} 

そして、私はこの方法作成しました:

//pass the arguments as JSON body 
@POST 
// Path: http://localhost:8080/UserAccount/rest/login/asklogin 
@Path("/askLogin") 
// Produces JSON as response 
@Consumes(MediaType.APPLICATION_JSON) 
@Produces(MediaType.APPLICATION_JSON) 
public Response askLogin(User user) { 
    System.out.println("Inside POST askLogin"); 
    if(checkCredentials(user.getUsername(), user.getPassword())) { 
     return Response.ok().build(); 
    } else { 
     return Response.serverError().build(); 
    } 
} 

私はGoogleのCからアドバンストレストクライアントを使用してAPIをテストしていますがhromeとRESTはFirefoxから簡単に。次のように

は私もMessageBodyReaderのを実装するクラスを作成しました:

@Provider 
public class UserBeanMessageBodyReader implements MessageBodyReader<User> { 

    //used for MessageBodyReader 
    @Override 
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, 
      MediaType mediaType) { 
     return type == User.class; 
    } 

    @Override 
    public User readFrom(Class<User> type, Type genericType, Annotation[] annotations, 
      MediaType mediaType, MultivaluedMap<String, String> httpHeaders, 
      InputStream entityStream) throws IOException, WebApplicationException { 
     try { 
      JAXBContext jaxbContext = JAXBContext.newInstance(User.class); 
      User user = (User) jaxbContext.createUnmarshaller().unmarshal(entityStream); 
      return user; 
     } catch (JAXBException jaxbException) { 
      jaxbException.printStackTrace(); 
      System.out.println("Error deserializing a User" + jaxbException); 
     } 
     return null; 
    } 
} 

デバッグした後、問題はここに来ている:

User user = (User) jaxbContext.createUnmarshaller().unmarshal(entityStream); 

、それはcatch文になります。

スタックトレースは以下の通りです:

INFO: Server startup in 1239 ms 
javax.xml.bind.UnmarshalException 
- with linked exception: 
[org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is 

    not allowed in prolog.] 
     at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335) 
     at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:563) 
     at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:249) 
     at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214) 
     at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157) 
     at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:204) 
     at ro.useraccount.jersey.UserBeanMessageBodyReader.readFrom(UserBeanMessageBodyReader.java:36) 
     at ro.useraccount.jersey.UserBeanMessageBodyReader.readFrom(UserBeanMessageBodyReader.java:1) 
     at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:393) 
     at com.sun.jersey.server.impl.model.method.dispatch.EntityParamDispatchProvider$EntityInjectable.getValue(EntityParamDispatchProvider.java:139) 
     at com.sun.jersey.server.impl.inject.InjectableValuesProvider.getInjectableValues(InjectableValuesProvider.java:43) 
     at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$EntityParamInInvoker.getParams(AbstractResourceMethodDispatchProvider.java:126) 
     at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:173) 
     at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:67) 
     at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:163) 
     at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:111) 
     at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:71) 
     at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:111) 
     at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:63) 
     at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:654) 
     at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:612) 
     at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:603) 
     at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:309) 
     at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:425) 
     at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:590) 
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:723) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) 
     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) 
     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) 
     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861) 
     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:612) 
     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503) 
     at java.lang.Thread.run(Thread.java:745) 
    Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog. 
     at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203) 
     at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:177) 
     at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:400) 
     at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:327) 
     at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1437) 
     at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:999) 
     at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606) 
     at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:118) 
     at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510) 
     at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848) 
     at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777) 
     at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) 
     at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213) 
     at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643) 
     at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:243) 
     ... 35 more 
    Error deserializing a Userjavax.xml.bind.UnmarshalException 
    - with linked exception: 
    [org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.] 
    Inside POST askLogin 
    Oct 06, 2016 8:57:27 AM org.apache.catalina.core.StandardWrapperValve invoke 
    SEVERE: Servlet.service() for servlet ServletAdaptor threw exception 
    java.lang.NullPointerException 
     at ro.useraccount.jersey.Login.askLogin(Login.java:67) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
     at java.lang.reflect.Method.invoke(Method.java:497) 
     at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:175) 
     at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:67) 
     at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:163) 
     at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:111) 
     at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:71) 
     at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:111) 
     at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:63) 
     at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:654) 
     at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:612) 
     at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:603) 
     at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:309) 
     at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:425) 
     at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:590) 
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:723) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) 
     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) 
     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) 
     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861) 
     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:612) 
     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503) 
     at java.lang.Thread.run(Thread.java:745) 

あなたはどう思いますか?

+0

私は恐れているジャージーがgsonまたはjettisonをすぐにサポートしてくれることを恐れています。 jacksonを使用するように変更するか、独自のメッセージ本体リーダーとライターを作成することができます。 – Veeram

答えて

3

JSONの処理にGsonを使用するようにJerseyに指示する必要があります。これは、Jerseyが提供するMessageBodyReaderおよびMessageBodyWriterインターフェースを実装することで可能です。 このstackoverflow questionに例を見つけることができます(受け入れられた回答を参照)。私はあなたのコードを理解することはできません が、どこ UserBeanMessageBodyReaderでGsonの呼び出しは次のとおりです。あなたはそれにいくつかのコンテキストを追加したい場合は 、 the JSON section of the Jersey 1.x manual

EDITを見てみましょうか? 代わりに(afaictのみXML入力を理解している)JAXBContextを使用しての

String result = new BufferedReader(new InputStreamReader(entityStream)) 
       .lines().collect(Collectors.joining("\n")); 
Gson gson = new GSon(); 
User myUser = gson.fromJson(result, User.class); 

の線に沿って何かをreaedFrom方法をchaging試してみてください。

+0

こんにちはFrancesco。今日の朝、私はMessageBodyReader(@Providerアノテーションで区切られたクラスを作成しました)を試しました。これで、メソッドaskLogin()の内部に入ることができ、最初の行「Inside POST askLogin」に文字列を出力していますが、まだアンマーシャリングできません。このエラーが発生する:javax.xml.bind.UnmarshalExceptionをデシリアライズする際のエラー - リンクされた例外: [org.xml.sax.SAXParseException; lineNumber:1; columnNumber:1;内容はプロローグで許可されていません。] –

+0

これはあなたが提供している入力と関係があると思います。例外を引き起こしているものを発見するには、 'MessageBodyReader'をデバッグする必要があります。それ以外の場合は、 'askLogin'サービスを' @Consumes( "text/plain") 'に一時的に変更し、' User user'の代わりに 'String user'を受け入れることができます。このようにして、Jerseyが入力として受け取っているものを見ることができ、Gsonがそれを好まない理由が分かるはずです。 –

+0

確かに、Setterメソッドを 'User'に追加してみてください。たぶん問題は、Gsonが 'User'のフィールドのセッターを見つけることができないことだけです。 –

関連する問題