Archive for the ‘ Java Technology ’ Category

JSF : java.lang.IllegalStateException: Cannot create a session after the response has been committed

เจอปัญหาในการใช้งาน JSF 2.1 และ RichFace 4.2 แล้วเกิดข้อผิดพลาดดังนี้

Jun 26, 2012 5:25:56 PM com.sun.faces.application.view.FaceletViewHandlingStrategy handleRenderException
SEVERE: Error Rendering View[/index.xhtml]
java.lang.IllegalStateException: Cannot create a session after the response has been committed
	at org.apache.catalina.connector.Request.doGetSession(Request.java:2754)
	at org.apache.catalina.connector.Request.getSession(Request.java:2264)
	at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:899)
	at com.sun.faces.context.ExternalContextImpl.getSession(ExternalContextImpl.java:155)
	at javax.faces.context.ExternalContextWrapper.getSession(ExternalContextWrapper.java:396)
	at com.sun.faces.renderkit.ServerSideStateHelper.writeState(ServerSideStateHelper.java:175)
	at com.sun.faces.renderkit.ResponseStateManagerImpl.writeState(ResponseStateManagerImpl.java:122)
	at com.sun.faces.application.StateManagerImpl.writeState(StateManagerImpl.java:166)

ซึ่งในหน้า index.xhtml มี code ประมาณนี้

<ui:composition xmlns="http://www.w3.org/1999/xhtml" 
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:ui="http://java.sun.com/jsf/facelets" 
                xmlns:rich="http://richfaces.org/rich" 
                template="/templates/index.xhtml">
    
    <ui:define name="title">RichFaces Sample</ui:define>
    <ui:define name="body">
        <h:panelGrid columns="1" columnClasses="cols" width="300">
            <h:form>
                <rich:panelMenu style="width:300px;" 
                                groupMode="client"
                                groupExpandedLeftIcon="triangleUp"
                                groupCollapsedLeftIcon="triangleDown" 
                                topGroupExpandedRightIcon="chevronUp"
                                topGroupCollapsedRightIcon="chevronDown" 
                                itemLeftIcon="grid">                    

                    <rich:panelMenuGroup label="Rich In Action">
                        <rich:panelMenuItem label="rich:popupPanel" action="rich/popup"/>
                        <rich:panelMenuItem label="rich:popupPanel [action]" action="rich/popup_action"/>
                        <rich:panelMenuItem label="rich:fileUpload" action="rich/upload"/>                        
                    </rich:panelMenuGroup>
                    <rich:panelMenuGroup label="Full Example">
                        <rich:panelMenuItem label="Full Example" action="rich/full-example"/>
                        <rich:panelMenuItem label="Converter" action="jsf/converter"/>
                        <rich:panelMenuItem label="Order Car" action="jsf/order-car"/>
                    </rich:panelMenuGroup>                      
                </rich:panelMenu>
            </h:form>
        </h:panelGrid>       
    </ui:define>    
</ui:composition>

ตอนแรกสงสัยว่าเกิดจาก ManageBean ไม่ได้ implement Serializable หรือเปล่าลองแก้แล้วก็ไม่หาย ลองลบ ออกแล้วรันใหม่ไม่เกิดข้อผิดพลาด สรุปว่่าปัญหาเกิดจาก จากการสอบถามข้อมูลจาก google ได้ความว่า ถ้ามีการใช้งาน PhaseListener จะเกิดข้อผิดพลาดแบบนี้ตอนเปิดใช้งานครั้งแรก หลังจาก start web server แล้ว วิธีแก้ไขคือ ให้ใส่

FacesContext.getCurrentInstance().getExternalContext().getSession(true);

ใน method public void beforePhase(PhaseEvent event) {} ดังนี้

public class SessionPhaseListener implements PhaseListener {
	public PhaseId getPhaseId() { 
		return PhaseId.RENDER_RESPONSE; 
	}
	public void afterPhase(PhaseEvent event) {
		//Implement
	}
 
	public void beforePhase(PhaseEvent event) {
		// we need to ask for the session early
		FacesContext.getCurrentInstance().getExternalContext().getSession(true);
	}
}

ลอง start server ใหม่อีกครั้งหายเป็นปลิดทิ้งๆๆๆๆๆๆ

แหล่งข้อมูล
[Richfaces 4] rich:panelMenu triggers IllegalStateException: Cannot create a session after the response has been committed

RichFaces : Component ID _viewRoot:status has already been found in the view.

ทดลองใช้ RichFaces แล้วต้องการให้แสดงสถานะแจ้งว่ากำลังทำงานอยู่ (Process Dialog) ซึ่งใน RichFaces นั้นมี Tag

<a4j:status />

ให้ใช้งานอยู่แล้ว เลยทดลองดังนี้

<a4j:status onstart="{Richfaces.showModalPanel('process-wait')};"
    onstop="{Richfaces.hideModalPanel('process-wait')};" />
<rich:modalPanel id="process-wait" width="250" height="100">
	<f:facet name="header">
		<h:outputText value="Processing" />
	</f:facet>
	<div align="center">
		<h:outputText value="Processing please wait..." /> <br>
	</div>
</rich:modalPanel>

พอทดลองรันแล้วเกิด Error ดังนี้

java.lang.IllegalStateException: Component ID _viewRoot:status has already been found in the view.  
	at com.sun.faces.util.Util.checkIdUniqueness(Util.java:724)
	at com.sun.faces.util.Util.checkIdUniqueness(Util.java:708)
	at com.sun.faces.application.StateManagerImpl.saveView(StateManagerImpl.java:129)
	at javax.faces.application.StateManager.saveSerializedView(StateManager.java:183)
	-
	-

Error ที่เกิดขึ้นเนื่องจากในหน้าจอ หรือ page นี้มีการใช้ tag จะไม่สามารถใช้ได้อีก วิธีการแก้ไข
1. ลบ Tag ที่ซ้ำออกแล้วสามารถใช้งานได้เลย
2. manual เปิด dialog เองในปุ่มที่ต้องการให้แสดง เช่น

<a4j:commandButton id="bt-action"
	value="Save" action="#{example.save}"
	onclick="{Richfaces.showModalPanel('process-wait')};"
	oncomplete="{Richfaces.hideModalPanel('process-wait')};" />

Update : 08/05/2012 สามารถใช้ tag หลายๆตัวในหน้าเดียวกันอ้างอิงจาก RichFaces Status โดยระบุ attribute “for” และกำหนด tag ครอบส่วนที่ต้องการให้เรียกใช้ เช่น

<a4j:region id="xx-yy">
     <a4j:commandButton id="bt-action"
	 value="Save" action="#{example.save}" />
</a4j:region>

<a4j:status for="xx-yy" onstart="{Richfaces.showModalPanel('id-here')};"
	onstop="{Richfaces.hideModalPanel('id-here')};" />

การใช้งาน Web Service JAX-WS 2.1.x ใน GlassFish V1.x (Sun Appication Server 8.2)

มีปัญหาเกี่ยวกับการใช้งาน Web Service client JAX-WS style ใน Sun Appication Server 8.2 ซึ่งไม่สามารถรันได้เกิด Error ดังนี้

java.lang.NoClassDefFoundError: javax/xml/ws/BindingProvider
    at java.lang.ClassLoade​r.defineClass1(Nativ​e Method)
    at java.lang.ClassLoade​r.defineClass(ClassL​oader.java:620)
    at java.security.Secure​ClassLoader.defineCl​ass(SecureClassLoade​r.java:124)
    at org.apache.catalina.​loader.WebappClassLo​ader.findClassIntern​al(WebappClassLoader​.java:1819)
    at org.apache.catalina.​loader.WebappClassLo​ader.findClass(Webap​pClassLoader.java:87​2)
    at org.apache.catalina.​loader.WebappClassLo​ader.loadClass(Webap​pClassLoader.java:13​27)
    at org.apache.catalina.​loader.WebappClassLo​ader.loadClass(Webap​pClassLoader.java:12​06)
    at java.lang.ClassLoade​r.loadClassInternal(​ClassLoader.java:319​)

เนื่องจาก Sun Appication Server 8.2 ที่ใช้งานอยู่ใช้ JDK 1.5 (5.0) ทำให้ไม่มี package javax/xml/ws/ ซึ่งตอนพัฒนาโปรแกรมนั้นในเครื่องสำหรับพัฒนาโปรแกรมใช้ JDK 1.6 (6.0) และใช้ GlassFish V2.1 (Sun Appication Server 9.1) ทำให้ไม่เจอปัญหาดังกล่าว จาการค้นหาข้อมูลการแก้ไขให้สามารถใช้งานได้ ให้ทำดังนี้
1. .ดาวน์โหลด JAX-WS 2.1 จากเว็บ http://jax-ws.java.net แล้วคัดลอก Library

FastInfoset.jar
activation.jar
http.jar
jaxb-api.jar
jaxb-impl.jar
jaxws-api.jar
jaxws-rt.jar
jsr173_api.jar
jsr181-api.jar
jsr250-api.jar
mimepull.jar
resolver.jar
saaj-api.jar
saaj-impl.jar
sjsxp.jar
stax-ex.jar
streambuffer.jar

ไปวางใน

<GlassFish Home>\domains\<domain name>\lib\ext

เนื่องจากไม่อยากให้กระทบกับ domain อื่นๆเลยคัดลอกมาวางใน lib ของ domain นั้นๆ โดย .jar ที่ต้องใช้มีดังนี้ JAX-WS 2.1 Jar dependency
2. จากนั้นทำการ stop/start Server ใหม่ ก็สามารถใช้ได้แล้ว

แหล่งข้อมูล
JAX-WS RI 2.1.3 Release Notes

Most important keyboard shortcuts in Eclipse

ห่างหายไปช่วงหนึ่งเนื่องจากงานสุมหัวมากไปหน่อย มีโอกาสได้กลับไปใช้ Eclipse ทำมาหากินอีกครั้งหลังจากที่ใช้งาน Netbeans มาพักใหญ่ เลยแวะไปเจอ Keyboard shortcuts ที่สำคัญและใช้งานบ่อยชนิดที่ ต้องจดบันทึกไว้ อ่านได้จาก

Eclipse Shortcuts for Increased Productivity

[Java] อ่านข้อมูลจาก XML โดยใช้ JDOM Parser

การอ่านข้อมูลจาก xml โดยใช้ Java นั้นมีหลายรูปแบบมากเนื่องจาก Java เองมี XML Parser อยู่หลายตัว สำหรับตัวอย่างนี้จะใช้ JDOM Parser ซึ่งเร็วกว่าตัวอื่น เนื่องจากไม่ไ่ด้ใช้ในการแก้ไขข้อมูล xml แต่เป็นการอ่านข้อมูลจาก xml เพียงอย่้างเดียว
1. โหลด jdom-x.x.jar จากนั้นก็ add เข้าไปในโปรเจค
2. ข้อมูลที่จะรับมาจาก ผู้ใช้งานโดยการ post เข้ามายัง Sevlet ที่เตรียมไว้จะมีลักษณะดังนี้

<Payments>
	<customer id='1'>
		<item>1001</item>
		<price>1000.00</price>
	</customer>
	<customer id='2'>
		<item>1002</item>
		<price>20.00</price>
	</customer>
</Payments>

3. เขียน code ดังนี้
Read more