2013-08-13 18 views
8

JAX-RSを介して配信したいGlassFish 4.0サーバーとサーバー側のJPAベースのクラスを使用しています。単純なエンティティの場合、これまでのところうまく動作します。しかし、たとえば@OneToMany関係があり、リンクされたエンティティがある場合、サーバーは500の内部サーバーエラーを返します。この場合、サーバーログには何も記録されません。エラーを見つけるために、小さなカスタムJSPページを作成して、何が起こったかについての詳細情報を取得しました。コードはちょうどこの次のとおりです。ただしGlassFish 4.0 with Jerseyは例外なく内部サーバーエラー500を返す

私自身のサーバー・サイドのコード(一部のデバッグ出力をしました)適切に実行するようだが、

Status: <%= pageContext.getErrorData().getStatusCode() %> 
Throwable: <%= pageContext.getErrorData().getThrowable() %> 

残念ながら、出力は単に「ヌル:500 Throwableのステータスが」 、いくつかのエラーが出ます。

Userクラス:

package my.application.model; 

import static javax.persistence.FetchType.LAZY; 

import java.io.Serializable; 
import java.util.List; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.OneToMany; 
import javax.persistence.Table; 
import javax.xml.bind.annotation.XmlRootElement; 

/** 
* The persistent class for the User database table. 
* 
*/ 
@XmlRootElement 
@Entity(name="User") 
@Table(name="User") 
public class User implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name="id") 
    private int id; 

    @Column(name="failedLogin") 
    private short failedLogin; 

    @Column(name="firstname") 
    private String firstname; 

    @Column(name="lastname") 
    private String lastname; 

    @Column(name="middlename") 
    private String middlename; 

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

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

    //bi-directional many-to-one association to IssueComment 
    @OneToMany(mappedBy="user", fetch = LAZY) 
    private List<IssueComment> issueComments; 

    //bi-directional many-to-one association to SignalComment 
    @OneToMany(mappedBy="user", fetch = LAZY) 
    private List<SignalComment> signalComments; 

    //bi-directional many-to-one association to SignalMeasure 
    @OneToMany(mappedBy="user", fetch = LAZY) 
    private List<SignalMeasure> signalMeasures; 

    public User() { 
    } 

    public int getId() { 
     return this.id; 
    } 

     // more getters and setters auto-generated by Eclipse 
     } 

Userクラス:

package my.application.model; 

import java.io.Serializable; 
import java.util.Date; 
import java.util.List; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.NamedQuery; 
import javax.persistence.OneToMany; 
import javax.persistence.Table; 
import javax.persistence.Temporal; 
import javax.persistence.TemporalType; 
import javax.xml.bind.annotation.XmlRootElement; 

@NamedQuery(
    name = "getSingleIssue", 
    query = "SELECT i FROM Issue i WHERE i.id = :id" 
) 
/** 
* The persistent class for the Issue database table. 
* 
*/ 
@XmlRootElement 
@Entity(name="Issue") 
@Table(name="Issue") 
public class Issue implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Column(name="id") 
    private int id; 

    @Column(name="concernedModule") 
    private String concernedModule; 

    @Column(name="createdate") 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date createdate; 

    @Column(name="duedate") 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date duedate; 

    @Column(name="priority") 
    private int priority; 

    @Column(name="reminderdate") 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date reminderdate; 

    @Column(name="responsibleUserId") 
    private int responsibleUserId; 

    @Column(name="sendingModule") 
    private String sendingModule; 

    @Column(name="severity") 
    private int severity; 

    @Column(name="status") 
    private int status; 

    @Column(name="title") 
    private String title; 

    // bidirectional many-to-one association to IssueComment 
    @OneToMany(mappedBy = "issue") 
    private List<IssueComment> issueComments; 

    public Issue() { 
    } 

    public int getId() { 
     return this.id; 
    } 

// more getters and setters.... 
} 

IssueComment:連結IssueCommentエンティティがある場合を除き、この例では、ユーザと問題のクラスは問題なく取得することができ

package my.application.model; 

import java.io.Serializable; 

import javax.persistence.*; 

import java.util.Date; 


/** 
* The persistent class for the IssueComment database table. 
* 
*/ 
@Entity(name="IssueComment") 
@Table(name="IssueComment") 
public class IssueComment implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue 
    @Column(name="id") 
    private int id; 

    @Lob 
    @Column(name="comment") 
    private String comment; 

    @Temporal(TemporalType.TIMESTAMP) 
    @Column(name="time") 
    private Date time; 

    //bi-directional many-to-one association to Issue 
    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name="issueId") 
    private Issue issue; 

    //bi-directional many-to-one association to User 
    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name="userId") 
    private User user; 

    public IssueComment() { 
    } 

    public int getId() { 
     return this.id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

// getters/setters.... 
} 

ウェブサービスは次のとおりです。

package my.application.server.webservice; 

import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 
import javax.ws.rs.QueryParam; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.ext.Provider; 

import org.glassfish.jersey.server.ResourceConfig; 

import my.application.data.UserStorage; 
import my.application.logger.Logger; 
import my.application.model.Signal; 
import my.application.model.SignalComment; 
import my.application.model.User; 

@Provider 
@Path("User") 
public class UserService extends ResourceConfig { 

    private UserStorage storage = new UserStorage(); 

    public UserService() { 
     this.packages("my.application.model"); 
    } 

    @Produces(MediaType.APPLICATION_XML) 
    @Path("load") 
    @GET 
    public User getUser(@QueryParam("id") int id) { 
     try { 
      Logger.getInstance().log("fetching id: " + id); 
      User u = storage.getUser(id); 
      Logger.getInstance().log("number of signal comments: " + u.getSignalComments().size()); 
      SignalComment sc = u.getSignalComments().get(0); 
      Logger.getInstance().log("Signal 0 comment: " + sc.getComment()); 
      Signal s = sc.getSignal(); 
      Logger.getInstance().log("Signal subject: " + s.getSubject()); 
      return u; 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     // this code is not being reached (so no errors in this method): 
     Logger.getInstance().log("---EXCEPTION HAS BEEN THROWN---"); 

     return null; 
    } 
} 

クライアントソースコードはサーバー側であり、通常のブラウザで再現できるので、ここではクライアントコードは必要ありません。

+0

nullポインタ例外のようです。デバッグできますか? –

+0

web.xmlで開発モードを有効にしていますか? – unwichtich

+0

@Sotirios:残念ながら、ログをFINESTに設定したり、デバッグモードでサーバーを起動しようとすると、GlassFishを起動しようとするとEclipseにTimeOutExceptionが発生します。私は開発モードを試してみます。現在はオンになっていません。 – grobmotoriker

答えて

8

XMLにマーシャリングしようとしているグラフ(オブジェクト)に循環参照がないことを確認してください。たとえば、これは問題を引き起こす可能性があります:

User -> IssueComment -> (the same) User 

または

User -> IssueComment -> Issue -> IssueComment -> (the same) User 

このような構造は、XMLに整列化することはできません。

注:(私はそれが必要ではないと思うが、それはそこにそれを持っている方が良いでしょう)IssueComment@XmlRootElement注釈を追加します。

注:ログの問題についてはわかっており、JERSEY-2000の一部として解決されます。

+0

ああ、ありがとう!私は明日それをチェックします! – grobmotoriker

+2

それだけです!情報をお寄せいただきありがとうございます。また、ロギングの問題に関する情報もあります。私は@XmlTransientで属性(この例では、IssueCommentのユーザーとissue属性)に注釈を付けました。そのため、オブジェクトをマーシャリングする際には考慮されません。 – grobmotoriker

+3

追加情報:その問題が発生している場合 - 属性ではなく、getterメソッドに@XmlTransientという注釈を付ける必要があります – grobmotoriker

関連する問題