AJAX Problem bei Seam (JSF/ Hibernate)

brunce

Grünschnabel
Hallo,

folgendes (einfaches?) Problem: Über eine Weboberfläche will ich den Inhalt einer Entity-Bean bearbeiten. Durch AJAX will ich die entsprechende Tabelle auf der Weboberfläche nach Hinzufügen oder Löschen von Einträgen aktualisieren.
Allerdings geschieht die Aktualisierung nicht gescheit, es wird ca. nur bei jedem zweiten neuen Eintragen korrekt aktualisiert, oder immer einen Eintrag zu spät. Das variiert aus mir unerfindlichen Gründen.
Wie man in der xhtml-Datei sehen kann, sind die links zum Löschen/ Hinzufügen direkt in jeder Zeile der Tabelle. Aber eigentlich kann es damit doch nichts zu tun haben!?

Was kann der Grund für das Verhalten sein? Wie kann ich den Fehler beheben?

Meine Theorie ist, das das reRendern und das Ausführen der Action-Methode von <a:support> gleichzeitig passiert. Kann das jemand bestätigen? Dazu habe ich nichts in der Dokumentation gefunden. Zum Googlen fehlen mir die Stichwörter, nach denen ich such könnte.

Ich benutze Seam 2.1.2

Folgend mein Code (kritische Kommentare erwünscht!)

editTableFailureLocations.xhtml
HTML:
	<a:outputPanel id="simpleDataPanel" >
		<h:dataTable id="simpleDataTable" value="#{locations}" var="row">
			<h:column>
				<f:facet name="header">
					#{messages.term_FLocation}
				</f:facet>
				
				<h:inputText value="#{row.name}" />
				
				<f:facet name="footer">
					<h:inputText value="#{editFailureLocations.newLocationName}" />
				</f:facet>
			</h:column>
			<h:column>
				<f:facet name="header">
					#{messages.term_FLocCat}
				</f:facet>	
						
				<h:selectOneMenu value="#{row.category}">
					<s:selectItems value="#{failureLocationCategoryDao.allActive}" var="cat" label="#{cat.name}" noSelectionLabel="" />
					<s:convertEntity />
				</h:selectOneMenu>
				
				<f:facet name="footer">
					<h:selectOneMenu value="#{editFailureLocations.newLocationCategory}">
						<s:selectItems value="#{failureLocationCategoryDao.allActive}" var="cat" label="#{cat.name}" noSelectionLabel="" />
						<s:convertEntity />
					</h:selectOneMenu>
				</f:facet>
			</h:column>
			<h:column>
				<s:link>
					#{messages.misc_Delete}
					<ui:remove>
						<h:graphicImage value="../images/delete.png" alt="#{messages.misc_Entry} #{messages.misc_Delete}" />
					</ui:remove>
					<a:support event="onclick"
						action="#{editFailureLocations.removeEntry}"
						reRender="simpleDataPanel" 
						eventsQueue="foo" />
				</s:link>
				
				<f:facet name="footer">
					<s:link>
						#{messages.misc_Add}
						<a:support event="onclick"
							action="#{editFailureLocations.addEntry}"
							reRender="simpleDataPanel" 
							eventsQueue="foo" />
					</s:link>
				</f:facet>
			</h:column>
		</h:dataTable>
		<h:commandButton action="#{editFailureLocations.saveChanges}" value="#{messages.misc_Save}" type="submit"/>
		<h:messages styleClass="message"/>
	</a:outputPanel>

editFailureLocations.java
Code:
@Name("editFailureLocations")
@Stateful
@Scope(ScopeType.SESSION)
public class EditFailureLocations implements EditFailureLocationsLocal {

	@Logger private Log log;
	
	@In FailureLocationDao failureLocationDao;
	@In FailureLocationCategoryDao failureLocationCategoryDao;
	
	@DataModel
	private List<FailureLocationEntity> locations;
	@DataModelSelection
	private FailureLocationEntity selectedLocation;
	
	private String newLocationName;
	private FailureLocationCategoryEntity newLocationCategory;

	@Create
	public void init() {
		log.info("editFailureLocations {0}", "init() ");
	}

	/**
	 * Initialisiert locations
	 */
	@Factory("locations")
	public void initLocations() {
		log.info("editFailureLocations {0}", "initLocations() ");
		locations = failureLocationDao.getAllActive();
			
		for(FailureLocationEntity l : locations) {
			log.info("editFailureLocations {0}", "   name " + l.getName());
		}
	}

	/**
	 * Löscht den gewählten Eintrag.
	 */
	public String removeEntry() {
		log.info("editFailureLocations {0}", "removeEntry() " + selectedLocation);
		
		failureLocationDao.remove((FailureLocationEntity) selectedLocation);	

		initLocations();
		return "";
	}

	/**
	 * Fügt einen neuen Eintrag hinzu.
	 */
	public String addEntry() {
		
		
		FailureLocationEntity newEntry;		
		if(newLocationCategory == null) {
			newEntry = new FailureLocationEntity(newLocationName, null);
			log.info("editFailureLocations {0}", "addEntry() " + newLocationName);
		} else {
			log.info("editFailureLocations {0}", "addEntry() " + newLocationName + newLocationCategory);
			newEntry = new FailureLocationEntity(newLocationName, newLocationCategory);			
		}		
		failureLocationDao.add(newEntry);
		
		initLocations();
		return "";
	}

	public void saveChanges() {		
		log.info("editFailureLocations {0}", "saveChanges() ");
		
		for(FailureLocationEntity l : locations) {
			failureLocationDao.update(l);			
		}
	}
	//getter und setter
}

editFailureLocations.java
Code:
@Local
public interface EditFailureLocationsLocal {

	public void init();
	public void initLocations();
	public String removeEntry();
	public String addEntry() ;
	public void saveChanges();	
	
	public String getNewLocationName();
	public void setNewLocationName(String newLocationName);	
	public FailureLocationCategoryEntity getNewLocationCategory();
	public void setNewLocationCategory(FailureLocationCategoryEntity newLocationCategorie);
	
	public void sayHello(String text);
	
	public void destroy() ;
}

FailureLocationDao.java
Code:
@Name("failureLocationDao")
@AutoCreate
public class FailureLocationDao {

	@In
	protected EntityManager em;

	@SuppressWarnings("unchecked")
	public List<FailureLocationEntity> getAllActive() {
		List<FailureLocationEntity> eList = em.createNamedQuery("FailureLocationEntity.getAllActive").getResultList();
		
		for(FailureLocationEntity e : eList) {
			e.getCategory();
		}
		
		return eList;
	}
	
	public void remove(FailureLocationEntity e) {
		e = em.merge(e);
		em.remove(e);	
		em.flush();
	}
	
	public void remove(List<FailureLocationEntity> list) {
		for(FailureLocationEntity e : list) {
			e = em.merge(e);
			em.remove(e);
		}				
		em.flush();
	}	
	
	public void add(FailureLocationEntity e) {
		em.persist(e);
		em.flush();
	}
	
	public FailureLocationEntity update(FailureLocationEntity e) {			
		return em.merge(e);
	}
}

FailureLocationEntity.java
Code:
@NamedQueries( {
	@NamedQuery(name = "FailureLocationEntity.getAll", query = "SELECT e FROM FailureLocationEntity e ORDER BY name"),
	@NamedQuery(name = "FailureLocationEntity.getAllActive", query = "SELECT e FROM FailureLocationEntity e WHERE isActive=true ORDER BY name")
	}
)
@Entity
@Table(name = "FAILURELOCATION")
public class FailureLocationEntity implements Serializable {

	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long id;
	
	private String name;
	
	private boolean isActive;
	
	@ManyToOne
	private FailureLocationCategoryEntity category;

	//getter und setter
}

FailureLocationCategoryEntity.java
Code:
@Entity
@Table(name = "FAILURELOCATIONCATEGORY")
public class FailureLocationCategoryEntity {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long id;

	private String name;

	private boolean isActive;

	//getter und setter
}


Vielen Dank für Eure Hilfe!

Edit: Wenn jemand eine Beispielanwendung kommt, die auch genau das macht: Immer her damit. Meine 5 Bücher und das Internet haben mir bisher nicht weitergeholfen
 
Zuletzt bearbeitet:
Hallo,

afaik funktioniert der ajax4jsf support Tag (<a:support>) nicht mit dem Seam link Tag (<s:link>). Vielleicht liegts ja daran.

Versuch doch mal den commandLink von ajax4jsf, der hat das rerender auch gleich drin. Du kanns natürlich auch den standard JSF-commandLink benutzen, dann brauchst du aber wieder den ajax4jsf support tag.

Grüße
THMD
 

Neue Beiträge

Zurück