2014-06-07 7 views
5

Ich habe einige Probleme in der Servlet wobei jedes Mal, wenn ich die Option in einem Dropdown-Menü, einen anderen Wert an das Servlet übergeben und dann führt es in eine Endlosschleife. Wenn ich die Option (keine Wertänderung) im Dropdown-Menü nicht ändere, gibt es keinen Fehler.Servlet Gson(). ToJson Endlosschleife

Hier ist mycode:

Mein Javascript:

<script> 

function loadStaff(){ 
//dropdown 
var positionDropDown = document.getElementById("positionsDropdown"); 
//value of the drop down 
var positionID = positionDropDown.options[positionDropDown.selectedIndex].value; 

    $.getJSON('loadStaff?positionID=' + positionID, function(data) { 
      -- no populate code yet 
}); 
} 
</script> 

Mein AjaxServlet:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 

     String userPath = request.getServletPath(); 

    if (userPath.equals("/loadStaff")) { 

     String positionID = request.getParameter("positionID"); 
     Position position = positionFacade.find(Integer.parseInt(positionID)); 
     Collection staffCollection = position.getStaffCollection(); 
     List<Staff> staffList = new ArrayList(staffCollection); 

     String staffListJson = new Gson().toJson(staffList); 
     response.setContentType("application/json"); 
     response.setCharacterEncoding("UTF-8"); 
     response.getWriter().write(staffListJson); 

    } 

} 

Nach debuggig. Der Fehler in Zeile kommt:

String staffListJson = new Gson().toJson(staffList); 

Ausgangsfehler:

> INFO: WebModule[null] ServletContext.log(): The server side 
> component of the HTTP Monitor has detected a 
> java.lang.StackOverflowError. This happens when there is an infinite 
> loop in the web module. Correct the cause of the infinite loop before 
> running the web module again. 
> 
> INFO: The server side component of the HTTP Monitor has detected a 
> java.lang.StackOverflowError. This happens when there is an infinite 
> loop in the web module. Correct the cause of the infinite loop before 
> running the web module again. WARNING: 
> StandardWrapperValve[AjaxServlet]: Servlet.service() for servlet 
> AjaxServlet threw exception java.lang.StackOverflowError 

> WARNING: StandardWrapperValve[AjaxServlet]: Servlet.service() for 
> servlet AjaxServlet threw exception java.lang.StackOverflowError at 
> sun.util.calendar.ZoneInfo.getOffsets(ZoneInfo.java:248) at 
> java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2276) 
> at 
> java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2248) 
> at java.util.Calendar.setTimeInMillis(Calendar.java:1140) at 
> java.util.Calendar.setTime(Calendar.java:1106) at 
> java.text.SimpleDateFormat.format(SimpleDateFormat.java:955) at 
> java.text.SimpleDateFormat.format(SimpleDateFormat.java:948) at 
> java.text.DateFormat.format(DateFormat.java:336) at 
> com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:90) 
> at 
> com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:41) 
> at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
> at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892) at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
> at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
> at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892) at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
> at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
> at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892) 

Ich habe auch bemerkt, dass diese Spuren nur Ausgabe von Stacktrace wiederholen;

EDIT: Staff Klasse

@Entity 
public class Staff implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "id") 
    private Integer id; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "last_name") 
    private String lastName; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "first_name") 
    private String firstName; 
    @Size(max = 45) 
    @Column(name = "middle_name") 
    private String middleName; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 6) 
    @Column(name = "gender") 
    private String gender; 
    @Basic(optional = false) 
    @NotNull 
    @Column(name = "date_of_birth") 
    @Temporal(TemporalType.DATE) 
    private Date dateOfBirth; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "nationality") 
    private String nationality; 
    @Basic(optional = false) 
    @NotNull 
    @Column(name = "date_hired") 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date dateHired; 
    @Size(max = 20) 
    @Column(name = "status") 
    private String status; 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "staff") 
    private Collection<StaffApointments> staffApointmentsCollection; 
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "staff") 
    private StaffContact staffContact; 
    @JoinColumn(name = "account_id", referencedColumnName = "id") 
    @ManyToOne(optional = false) 
    private Account accountId; 
    @JoinColumn(name = "position_id", referencedColumnName = "id") 
    @ManyToOne(optional = false) 
    private Position positionId; 

    public Staff() { 
    } 

    public Staff(Integer id) { 
     this.id = id; 
    } 

    public Staff(Integer id, String lastName, String firstName, String gender, Date dateOfBirth, String nationality, Date dateHired) { 
     this.id = id; 
     this.lastName = lastName; 
     this.firstName = firstName; 
     this.gender = gender; 
     this.dateOfBirth = dateOfBirth; 
     this.nationality = nationality; 
     this.dateHired = dateHired; 
    } 

    public Integer getId() { 
     return id; 
    } 

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

    public String getLastName() { 
     return lastName; 
    } 

    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 

    public String getFirstName() { 
     return firstName; 
    } 

    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 

    public String getMiddleName() { 
     return middleName; 
    } 

    public void setMiddleName(String middleName) { 
     this.middleName = middleName; 
    } 

    public String getGender() { 
     return gender; 
    } 

    public void setGender(String gender) { 
     this.gender = gender; 
    } 

    public Date getDateOfBirth() { 
     return dateOfBirth; 
    } 

    public void setDateOfBirth(Date dateOfBirth) { 
     this.dateOfBirth = dateOfBirth; 
    } 

    public String getNationality() { 
     return nationality; 
    } 

    public void setNationality(String nationality) { 
     this.nationality = nationality; 
    } 

    public Date getDateHired() { 
     return dateHired; 
    } 

    public void setDateHired(Date dateHired) { 
     this.dateHired = dateHired; 
    } 

    public String getStatus() { 
     return status; 
    } 

    public void setStatus(String status) { 
     this.status = status; 
    } 

    @XmlTransient 
    public Collection<StaffApointments> getStaffApointmentsCollection() { 
     return staffApointmentsCollection; 
    } 

    public void setStaffApointmentsCollection(Collection<StaffApointments> staffApointmentsCollection) { 
     this.staffApointmentsCollection = staffApointmentsCollection; 
    } 

    public StaffContact getStaffContact() { 
     return staffContact; 
    } 

    public void setStaffContact(StaffContact staffContact) { 
     this.staffContact = staffContact; 
    } 

    public Account getAccountId() { 
     return accountId; 
    } 

    public void setAccountId(Account accountId) { 
     this.accountId = accountId; 
    } 

    public Position getPositionId() { 
     return positionId; 
    } 

    public void setPositionId(Position positionId) { 
     this.positionId = positionId; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 0; 
     hash += (id != null ? id.hashCode() : 0); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object object) { 
     // TODO: Warning - this method won't work in the case the id fields are not set 
     if (!(object instanceof Staff)) { 
      return false; 
     } 
     Staff other = (Staff) object; 
     if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return "entity.Staff[ id=" + id + " ]"; 
    } 

} 

Hier ist die Position Klasse auch:

@Entity 
public class Position implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "id") 
    private Integer id; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "name") 
    private String name; 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "positionId") 
    private Collection<Staff> staffCollection; 

    public Position() { 
    } 

    public Position(Integer id) { 
     this.id = id; 
    } 

    public Position(Integer id, String name) { 
     this.id = id; 
     this.name = name; 
    } 

    public Integer getId() { 
     return id; 
    } 

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

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @XmlTransient 
    public Collection<Staff> getStaffCollection() { 
     return staffCollection; 
    } 

    public void setStaffCollection(Collection<Staff> staffCollection) { 
     this.staffCollection = staffCollection; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 0; 
     hash += (id != null ? id.hashCode() : 0); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object object) { 
     // TODO: Warning - this method won't work in the case the id fields are not set 
     if (!(object instanceof Position)) { 
      return false; 
     } 
     Position other = (Position) object; 
     if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return "entity.Position[ id=" + id + " ]"; 
    } 

} 

EDIT 2:

I @expose auf die Attribute hinzugefügt meine Mitarbeiterklasse mit Ausnahme von staffCollection. Aber ich habe immer noch ein Problem. Jedes Mal, wenn der erste Wert in der Dropdown-Liste ausgewählt wird (Wert = 1), wird immer noch der Endlosfehler ausgegeben. Kann mir jemand helfen?

EDIT 3:

es behoben! Ich habe den letzten GsonBuilder-Builder hinzugefügt = new GsonBuilder(); builder.excludeFieldsWithoutExposeAnnotation(); als Ganzes. Es funktioniert jetzt

+0

Servlet klingt wie Java zu mir und Ihre Fehler sehen, um diesen Gedanken zu validieren ... vielleicht wäre die Verwendung eines Java-Tags hilfreich? –

+0

Verwenden Sie nicht den Raw-Typ, wie hier verwendet 'Collection staffCollection', dann wird er ohne Überprüfung in die allgemeine' Liste' umgewandelt. * Das würde wahrscheinlich passieren, wenn Sie einen Zirkelverweis haben. * Dies führt beim Analysieren zu einer Endlosschleife. Teilen Sie auch die Klassen "Posiiton" und "Staff". – Braj

+0

@Braj Meine Klassen werden als Entitätsklassen aus der Datenbank generiert. Die Tabelle "Staff" referenziert ihre position_id aus der Tabelle "Position". Verzeihen Sie, wenn ich Sie nicht klar verstehen kann, was würden Sie in Ihrem Verweis auf die Sammlung von staffCollection vorschlagen? – MLDS

Antwort

7

Das Problem ist, dass jedes Staff Objekt eine Position Objekt enthält, das ein Collection von Staff Objekte enthält, die jeweils wieder ein Collection von Staff Objekte enthalten, usw. Gson wird diesen Baum zu Fuß für immer, weil es nie gonna stop ist .

Um es zu lösen, können Sie einen Blick auf die Antworten auf this Frage werfen.

+0

Vielen Dank für die Weiterleitung. Ich habe ein wenig Schwierigkeiten zu verstehen, was ich zeigen soll. Soll ich die Position positionID in der Staff-Klasse angeben? Es gibt mir immer noch Fehler. Können Sie bitte klarstellen? – MLDS

+0

Nein, Sie sollten alle Elemente mit Ausnahme derer, die Sie nicht in Ihrem JSON –

+0

verfügbar machen wollen. Würde dies meine CRUD-Operationen beeinträchtigen? – MLDS