แสดงบทความที่มีป้ายกำกับ java แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ java แสดงบทความทั้งหมด
For JPA, it should work fine:
String jpql = "from A where name in (:names)";
Query q = em.createQuery(jpql);
q.setParameter("names", l);
For Hibernate's, you'll need to use the setParameterList:
String hql = "from A where name in (:names)";
Query q = s.createQuery(hql);
q.setParameterList("names", l);
Junit 4.11 comes with @FixMethodOrder annotation. Instead of using custom solutions just upgrade your junit version and annotate test class with FixMethodOrder(MethodSorters.NAME_ASCENDING). Check the release notes for the details.
Here is a sample:
import org.junit.runners.MethodSorters;

import org.junit.FixMethodOrder;
import org.junit.Test;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {

    @Test
    public void firstTest() {
        System.out.println("first");
    }

    @Test
    public void secondTest() {
        System.out.println("second");
    }
}

What’s internal resource views?

In Spring MVC or any web application, for good practice, it’s always recommended to put the entire views or JSP files under “WEB-INF” folder, to protect it from direct access via manual entered URL. Those views under “WEB-INF” folder are named as internal resource views, as it’s only accessible by the servlet or Spring’s controllers class. In Spring MVC, InternalResourceViewResolver is used to resolve “internal resource view” (in simple, it’s final output, jsp or htmp page) based on a predefined URL pattern. In additional, it allow you to add some predefined prefix or suffix to the view name (prefix + view name + suffix), and generate the final view page URL.

Java : Setting Locale System Properties

System PropertyDescription
user.language
Two-letter language name code based on ISO 639.
user.region
Two-letter region name code based on ISO 3166.
file.encoding
Default character-encoding name based on the IANA Charset MIB.


ex.
-Duser.country=US -Duser.language=en

Ref: 1.

ดู locale ได้จาก Ref

Webservice client ignore SSL certificate errors


If you are dealing with a web service call using the Axis framework, there is a much simpler answer. If all want is for your client to be able to call the SSL web service and ignore SSL certificate errors, just put this statement before you invoke any web services:
System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");
The usual disclaimers about this being a Very Bad Thing to do in a production environment apply.
I found this at the Axis wiki.
String is immutable whereas StringBuffer and StringBuilder can change their values.

The only difference between StringBuffer and StringBuilder is that StringBuilder is unsynchronized whereas StringBuffer is synchronized. So when the application needs to be run only in a single thread then it is better to use StringBuilder. StringBuilder is more efficient than StringBuffer.

Criteria to choose among String, StringBuffer and StringBuilder

1. If your text is not going to change use a string Class because a String object is immutable.
2. If your text can change and will only be accessed from a single thread, use a StringBuilder because StringBuilder is unsynchronized.http://www.blogger.com/img/blank.gif
3. If your text can changes, and will be accessed from multiple threads, use a StringBuffer because StringBuffer is synchronous.

Ref : link 1


link 2

link 3

การ Set Connection Timeout ใน Socket

มีสองตัวให้ Config น่ะครับ เป็น soTimeout ของ Socket อันนี้คือระยะเวลา Ideal ของ Socket ถ้าเกินก็จะ Timeout ออกไปต้อง Connect ใหม่ กับ ตอน socket.connect (InetSocketAddress, Timeout) อันนี้จะเป็น Timeout ของการรอตอบกลับค่าจาก External System ที่เราไปเรียก ซึ่ง ตามตัวอย่างข้างล่าง



InetSocketAddress socketAddr = new InetSocketAddress(url,port);
Socket socket = new Socket();
socket.connect(socketAddr,readTimeout);
socket.setSoTimeout(idealTimeout);



Often we need to create a (client) socket connection in java but we do not want to wait indefinitely for the connection to open. We need a way to timeout socket connections. Two solutions and recommended code.

Previously the only way was to create the socket in a Thread. And then kill the thread if it is running beyond a threshold time limit. This had two problems. First Thread.kill or Thread.suspend are deprecated methods and with good reason. Their availability cannot be ensured in future versions of Java. Secondly the process was clumsy to say the least. Now we have a better method since JDK 1.4.

java.net.Socket supports timeout from JDK1.4 onwards. The following is a sample code to enable socket timeout in Java. In this sample 500 milliseconds is chosen as timeout value.


// Open a socket without any parameters. It hasn’t been binded or connected
Socket sock = new Socket();

// Bind to a local ephemeral port
sock.bind(null);

// Connect to google.com on port 80 with a timeout of 500 milliseconds
sock.connect(new InetSocketAddress(”www.google.com”, 80), 500);

// Your code goes here

// Close the socket.
sock.close();

Hibernate call store procedure

In Hibernate, there are three approaches to call a database store procedure.
1. Native SQL – createSQLQuery

You can use createSQLQuery() to call a store procedure directly.

Query query = session.createSQLQuery(
"CALL GetStocks(:stockCode)")
.addEntity(Stock.class)
.setParameter("stockCode", "7277");

List result = query.list();
for(int i=0; i Stock stock = (Stock)result.get(i);
System.out.println(stock.getStockCode());
}


2. NamedNativeQuery in annotation
Declare your store procedure inside the @NamedNativeQueries annotation.


//Stock.java
...
@NamedNativeQueries({
@NamedNativeQuery(
name = "callStockStoreProcedure",
query = "CALL GetStocks(:stockCode)",
resultClass = Stock.class
)
})
@Entity
@Table(name = "stock")
public class Stock implements java.io.Serializable {
...


Call it with getNamedQuery().


Query query = session.getNamedQuery("callStockStoreProcedure")
.setParameter("stockCode", "7277");
List result = query.list();
for(int i=0; i Stock stock = (Stock)result.get(i);
System.out.println(stock.getStockCode());
}


3. sql-query in XML mapping file

Declare your store procedure inside the “sql-query” tag.

<!-- Stock.hbm.xml -->
...
<hibernate-mapping>
<class name="com.mkyong.common.Stock" table="stock" ...>
<id name="stockId" type="java.lang.Integer">
<column name="STOCK_ID" />
<generator class="identity" />
</id>
<property name="stockCode" type="string">
<column name="STOCK_CODE" length="10" not-null="true" unique="true" />
</property>
...
</class>

<sql-query name="callStockStoreProcedure">
<return alias="stock" class="com.mkyong.common.Stock"/>
<![CDATA[CALL GetStocks(:stockCode)]]>
</sql-query>

</hibernate-mapping>


Call it with getNamedQuery().


Query query = session.getNamedQuery("callStockStoreProcedure")
.setParameter("stockCode", "7277");
List result = query.list();
for(int i=0; i Stock stock = (Stock)result.get(i);
System.out.println(stock.getStockCode());
}


Conclusion

The above three approaches are doing the same thing, call a store procedure in database. There are not much big different between the three approaches, which method you choose is depend on your personal prefer.

Ref : link1
Supposing you have the following Oracle Stored procedure:

CREATE FUNCTION agenda RETURN SYS_REFCURSOR
AS
my_cursor SYS_REFCURSOR;
BEGIN
OPEN my_cursor FOR
SELECT id,person_name,person_surname,person_address
FROM Person;
RETURN my_cursor;
END;

Invoking it from Hibernate requires mapping the Stored Procedure in the Person class.


<sql-query name="SP_agenda" callable="true">
<return alias="ev" class="Person">
<return-property name="id" column="id"/>
<return-property name="name" column="person_name"/>
<return-property name="surname" column="person_surname"/>
<return-property name="address" column="person_address"/>
</return>
{ ? = call agenda() }
</sql-query>


Then, you can execute the procedure just like a normal Query:

Query query = session.getNamedQuery("SP_agenda");
List results = query.list();

certificate expired ซะงั้นดูจากปีพ.ศ.แล้ว (2497) น่าจะเกิดตอนลง SDK แล้วเครื่องเราตั้งระบบวันที่ของไทย เลยได้ certificate expired มาผิด

วิธีแก้ตามที่หลายเว็บแนะนำคือให้ไปลบไฟล์ “debug.keystore” ถ้าเป็น vista หรือ 7 อยู่ที่ C:\Users\ชื่อเครื่อง\.android ถ้า xp ก็อยู่ที่ C:\Documents and Settings\ชื่อเครื่อง\.android จากนั้นให้ไปเปลี่ยนภาษาใน control panel >> Regional and Language Options เป็น English(United States) แต่ลองแล้วก็ error เหมือนเดิม ไปเจออีกวิธีนึงได้ผลชะงักเลยตามด้านล่างครับ

เปิด command prompt แล้วพิมพ์



keytool -genkey -keypass android -keystore debug.keystore -alias androiddebugkey -storepass android -validity 10000 -dname "CN=Android Debug,O=Android,C=US"

ref : link1 , link2

เรื่องของ Serializable

อ่านในกระทู้ ปัญหากับ method setAttribute(), non-serializable (Narisa.com) มีความรู้ดีๆหลายเรื่อง
1. คุณ Siros post:
เนื่อง จากว่า Servlet container อาจจะไม่ได้ handle object ใน session เป็น local object เสมอไป .. เป็นไปได้ว่า เรา deploy server เป็น cluster แล้วให้ server มันทำ session replication (จะได้ทำ fail-over ได้) ... ดังนั้น object จาก session ใน server หนึ่ง อาจจะต้องถูกส่งไป เพื่อ synchronize กับ session ใน server อื่นๆ ด้วย ... นี่เป็นเหตุผลว่าทำไม ถึงต้อง Serializable ครับ
2. คุณ nohc post:
สิ่งที่กำหนดว่า Object นั้นคือตัวเดียวกันในการ De/Serialize คือ attribute serialVersionUID ใน Class นั่นเองครับ ถ้าอย่างนั้น hashCode() กับ equals() ไว้ทำอะไร สองตัวนี้ใช้ในการเปรียบเทียบ Object กับการทำ hash code ครับ เช่น Object ที่ใส่ไว้ใน HashMap ควรจะต้อง implement สอง method นี้ ยังมีอีกตัวครับที่ออกจะคุ้นเคยกันอยู่คือ compareTo(), method นี้จะใช้ใน Comparator หรือการ Sorting เท่านั้นครับ
- serialVersionUID ใช้ใน Serializable
- hashCode(), equals() ใช้ใน Hash
- compareTo() ใช้ใน Comparator
เหตุผล ของการ Serializable ไม่ใช่แค่เรื่องของ Session Replication เท่านั้นน่ะครับ การแปลง Object จะรูปแบบหนึ่งไปยังอีกรูปแบบหนึ่ง หรือเมื่อไรก็ตามที่ JVM ทำการเรียก writeObject() และ readObject() ตัว Object นั้น ๆ ต้องทำการ Serializable เสมอ
เช่นการแปลง Object เป็น file, ส่งผ่าน Object ทาง Network, เก็บ Object ลง Session, เรียก Object ผ่าน RMI เป็นต้นครับ
- ทำไม่แทบไม่เห็นใครใส่ Attribute serialVersionUID ลงใน Class ของเขาเวลา implement Serialzable
เพราะ ว่ากระบวนการของ JVM เวลาเราทำการประกาศ Class โดยการ implement Serializable ตัว JVM เองจะทำการตรวจสอบดูก่อนว่าเรามีการประกาศ Attribute serialVersionUID หรือเปล่า ถ้าไม่มีการประกาศ JVM จะทำการ Generate serialVersionUID ให้เราเองครับ ดังนั้นจึงไม่จะเป็นที่ต้องใส่ serialVersionUID เองใน Class อย่างไรก็ดีทาง SUN ใน strongly recommended ให้ทำการ ใส่ serialVersionUID ลงใน Class ของเรา เนื่องจากว่าในโลกนี้ไม่ได้มีแค่ SUN JVM ไงครับ SUN JVM ทำการ generate serialVersionUID ให้แต่ BEA, IBM, GNU, Microsoft JVM อาจไม่ได้ทำให้เราก็ได้ไงครับ

- แล้ว hashCode() กับ equals() จำเป็นแค่ไหนในการ implement ตัว JVM เองสามารถ generate ให้เหมือน serialVersionUID หรือไม่
คำ ตอบคือจำเป็นครับ และตัว JVM ก็ generate ให้ด้วย ที่บอกว่าจำเป็นเพราะว่า default generator ของ JVM จะทำการ generate hash code โดยเอา memory address ของ Object นั้นมาทำการ generate และ method equals() จะทำการเปรียบเทียบ โดยใช้ address เป็นตัวเปรียบเทียบครับ หมายความว่าทุกครั้งที่เราทำการ allocate memory ให้ Object ตัวใหม่ ก็จะ้ได้ hashCode() คนละตัวกันถึงแม้ว่า Object ของเรานั้นจะมีค่าเดียวกันก็ตาม เพราะฉะนั้นเมื่อไรก็ตามที่เราต้องการ identify Object ของเราโดย value ไม่ใช่ address เราก็ตัอง implement hashCode() กับ equals() เสมอครับ

Ref : link1

XPath หมายถึงภาษานึงที่ใช้งานร่วมกับ XML เพื่อใช้ในการดึงข้อมูลออกจากเอกสาร XML เป็นภาษาง่าย ๆ ในการใช้งาน สมมติเรามีข้อมูล XML ดังนี้ (ไฟล์ Berryz_Kobo.xml ในตัวอย่าง)

ปล , สามารถโหลด Code ตัวอย่าง ไฟล์ข้อมูลทั้งหมดได้ที่นี่ -> Example - XPath with Java.rar

--------------------------------------------------------------------------------------

Shimizu Saki
Tsugunaga Momoko
Sugaya Risako
Nutsuyaki Miyabi
Kumai Yurina
Tokunaga Chinami
Sudou Maasa
Ishimura Maiha


Anata Nashide wa Sekite Yukenai


Fighting Pose wa Date Janai


Piriri To Ikou


Happiness Koufuku Kangei


Koi no Jubaku


Special Generation


Nanchuu Koi wo Yatteruu YOU KNOW


21ji made no Cinderella


Gyagu 100kai bun Aishite Kudasai


Jiriri Kiteru


Waracchaou yo BOYFRIEND


Munasawagi Scarlet


VERY BEAUTY


Kokuhaku no Funsui Hiroba


Tsukiatte Iru noni Kataomoi



--------------------------------------------------------------------------------------
จากข้อมูล XML ที่ให้มา สมมติว่าต้องการจะอ่านข้อมูลชื่อ Single ทั้ง 15 ออกมา หากใช้ Java ปกติอ่านเข้ามา จะใช้ DOM (Document Object Model) อ่านเข้ามา ดัง Code ข้างล่าง (สร้างไฟล์อ่าน XML ชื่อ XMLRead.java)
--------------------------------------------------------------------------------------
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

public class XMLRead {

public static void main(String[] args) throws Exception {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse(new File("Berryz_Kobo.xml"));
Node berryzNode = doc.getFirstChild();
System.out.println("ROOT NODE NAME = "+berryzNode.getNodeName());
NodeList childNodes = berryzNode.getChildNodes();
for(int i=0; i < childNodes.getLength() ; i++){
Node dataNode = childNodes.item(i);
if( "singles".equalsIgnoreCase(dataNode.getNodeName())){
NodeList singleNodes = dataNode.getChildNodes();
for(int j=0; j < singleNodes.getLength() ; j++){
Node singleNode = singleNodes.item(j);
if( "single".equalsIgnoreCase( singleNode.getNodeName()) ){
NodeList nameNodes = singleNode.getChildNodes();
for(int k=0; k < nameNodes.getLength() ; k++){
Node nameNode = nameNodes.item(k);
if( "name".equalsIgnoreCase( nameNode.getNodeName())){
NodeList textNodes = nameNode.getChildNodes();
for(int l=0; l < textNodes.getLength() ; l++){
Node textNode = textNodes.item(l);
if( textNode.TEXT_NODE == textNode.getNodeType() ){
System.out.println("SINGLE = "+textNode.getNodeValue());
}
}
}
}
}
}
}
}
}

}
--------------------------------------------------------------------------------------
เมื่อสั่งรันดูจะได้ผลดังนี้ (ต้องมีไฟล์ Berryz_Kobo.xml อยู่ในโฟลเดอร์เดียวกับไฟล์ XMLRead.java ด้วย)

java_xml_xpath_1


รูปแบบการอ่านของ DOM จะเป็นแบบ Tree ที่เริ่มจาก Root Node เสมอ ดังนั้นเมื่อสั่ง doc.getFirstChild() จะได้ berryzNode มา และจาก Root Node เราสามารถเข้าถึง Node ย่อย ๆ ได้ โดยเรียก getChildNodes() method ซึ่งการที่เราจะเอาชื่อ Single ออกมา ก็ต้องเข้าไปถึง “name” node ที่อยู่ภายใต้ “single” node (แต่ละ tag ก็คือ node ย่อยนั่นเอง) มีข้อสังเกตนิดนึงว่าข้อความ Text ใน Node นั้น จะถูกถือเป็น childNode ของ node นั้น ๆ โดยมี Type เป็น TEXT_NODE (จะเห็นว่าไม่ใช่ getNodeValue() ของ Node “name” แต่เป็น getNodeValue() ของ childNode ของ “name” Node ที่มี Type เป็น TEXT_NODE แทน)
จะเห็นว่ากว่าจะได้ข้อความมาแต่ละอันนั้นช่างลำบากยากเย็นเสียเหลือเกิน วนลูปกันจนเหนื่อย XPath สามารถช่วยลดเวลาเราได้ ดังนี้
สร้างไฟล์ XpathRead.java ขึ้นมา มี Code ดังข้างล่าง (ไว้ที่เดียวกับ XMLRead.java และ Berryz_Kobo.xml)
--------------------------------------------------------------------------------------
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

public class XPathRead {

public static void main(String[] args) throws Exception {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse(new File("Berryz_Kobo.xml"));

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile("//name/text()");

Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList textNameNodes = (NodeList) result;
for (int i = 0; i < textNameNodes.getLength(); i++) {
Node textNode = textNameNodes.item(i);
System.out.println("Single = "+textNode.getNodeValue());

}
}

}
--------------------------------------------------------------------------------------
เมื่อสั่งรันโปรแกรม ได้ผลดังนี้

java_xml_xpath_2

สังเกตว่าใช้ XPath Query เป็น “//name/text()” ในการดึง text node ออกมาจาก node “name” โดย // หมายถึงให้วิ่งหา node ทุกตัวภายใต้ XML ปัจจุบัน (เมื่อใส่ //name จึงหมายถึงหา Node ที่มีชื่อว่า “name” ออกมาจาก XML ) /text() คือให้เอา text node ภายใต้ node ก่อนหน้าออกมา
ในความจริงการใช้ // ค่อนข้างจะเปลือง Performance ของโปรแกรมพอสมควร (เพราะวิ่งหาทั้ง XML เลย) เราสามารถเขียนให้ยาวขึ้นหน่อยนึง แต่มีประสิทธิภาพดีขึ้น โดยใช้ XPath Query เป็น “/berryz/singles/single/name/text()” (ทดลองเปลี่ยนดูได้ จะพบว่าให้ผลเหมือนเดิมเป๊ะ)

อันนี้เป็นเรื่องปกติของ XML คนที่ศึกษาอาจจะรู้อยู่แล้ว ทีนี้มาถึงเรื่องหลักที่อยากเขียนจริง ๆ เกี่ยวกับการใช้ XPath กับ Java ก็คือ เมื่อคุณไปเจอ XML ที่มีการระบุ Namespace คุณจะพบว่าการอ้างชื่อของ XML นั้นด้วย XPath จะไม่สามารถทำได้ ดังนี้
1. สร้างไฟล์ XML ที่มีการระบุ Namespace ชื่อ Berryz_Kobo_NS.xml ข้างในมีเนื้อหาดังนี้
--------------------------------------------------------------------------------------
xmlns="http://boris-chung.live.space.com">
Shimizu Saki
Tsugunaga Momoko
Sugaya Risako
Nutsuyaki Miyabi
Kumai Yurina
Tokunaga Chinami
Sudou Maasa
Ishimura Maiha


Anata Nashide wa Sekite Yukenai


Fighting Pose wa Date Janai


Piriri To Ikou


Happiness Koufuku Kangei


Koi no Jubaku


Special Generation


Nanchuu Koi wo Yatteruu YOU KNOW


21ji made no Cinderella


Gyagu 100kai bun Aishite Kudasai


Jiriri Kiteru


Waracchaou yo BOYFRIEND


Munasawagi Scarlet


VERY BEAUTY


Kokuhaku no Funsui Hiroba


Tsukiatte Iru noni Kataomoi



--------------------------------------------------------------------------------------
สังเกตว่ามีการใส่ xmlns=http://boris-chung.live.space.com เพิ่มเติมเข้าไปใน root node แบบนี้คือการเพิ่ม Namespace เข้าไป การเพิ่มเข้าไปแบบนี้จะทำให้ childNode ของ node ที่เพิ่ม มีผลอยู่ใน Namespace ที่กำหนดด้วย
2. ลองสร้างไฟล์ XPathReadNS.java ขึ้นมา ข้างในมีเนื้อหาเหมือนไฟล์ XPathRead.java เพียงแต่เปลี่ยนไปอ่านไฟล์ Berryz_Kobo_NS.xml แทน ดังนี้
--------------------------------------------------------------------------------------

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

public class XPathReadNS {

public static void main(String[] args) throws Exception {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse(new File("Berryz_Kobo_NS.xml"));

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile("/berryz/singles/single/name/text()");

Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList textNameNodes = (NodeList) result;
for (int i = 0; i < textNameNodes.getLength(); i++) {
Node textNode = textNameNodes.item(i);
System.out.println("Single = "+textNode.getNodeValue());

}
}

}
--------------------------------------------------------------------------------------
เมื่อสั่งรันโปรแกรมดู จะได้ผลดังนี้

java_xml_xpath_3

ไม่ปรากฏอะไรขึ้นมาเลย (อันนี้รันบน Editplus พอรันเสร็จมันจะหยุดให้กดคีย์ใด ๆ ให้อัตโนมัติ แต่ถ้ารันบน Command-Prompt จะผ่านไปเลย) ทั้งนี้เพราะ XPath ไม่สามารถเข้าถึง Node ใด ๆ ที่มีการกำหนด Namespace เอาไว้ได้ หากไม่กำหนด Namespace ให้กับ XPath ก่อน ซึ่งขั้นตอนในการที่จะทำให้ XPath สามารถใช้งานกับ Node ที่มีการกำหนด Namespace เอาไว้นั้น ทำได้ดังนี้
1) สร้าง Class ที่ implement class “NamespaceContext” ดังนี้ (ในที่นี้ใช้ชื่อไฟล์ NamespaceContextProvider.java)
--------------------------------------------------------------------------------------

import java.util.Iterator;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;

public class NamespaceContextProvider implements NamespaceContext {
String boundPrefix, boundURI;

NamespaceContextProvider (String prefix, String URI) {
boundPrefix = prefix;
boundURI = URI;
}

public String getNamespaceURI (String prefix) {
if (prefix.equals(boundPrefix)) {
return boundURI;
}
else if (prefix.equals(XMLConstants.XML_NS_PREFIX)) {
return XMLConstants.XML_NS_URI;
}
else if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) {
return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
}
else {
return XMLConstants.NULL_NS_URI;
}
}

public String getPrefix (String namespaceURI) {
if (namespaceURI.equals(boundURI)) {
return boundPrefix;
}
else if (namespaceURI.equals(XMLConstants.XML_NS_URI)) {
return XMLConstants.XML_NS_PREFIX;
}
else if (namespaceURI.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
return XMLConstants.XMLNS_ATTRIBUTE;
}
else {
return null;
}
}

public Iterator getPrefixes (String namespaceURI) {
return null;
}
}
--------------------------------------------------------------------------------------
ในการ implement class นี้ต้อง implement 3 method โดยเราจะกำหนด prefix ที่ต้องการใช้จับคู่กับ Namespace และค่า uri ของ Namespace ของ tag นั้น ๆ ตอนนี้ดู ๆ ไปอาจจะยังไม่เข้าใจ ให้เข้าใจง่าย ๆ ว่า Copy ไปเลยก็แล้วกัน ง่ายดี
2) ใน Code ที่จะเรียกใช้งาน XPath นั้น เพิ่มการกำหนด Namespace เข้าไปดังนี้
--------------------------------------------------------------------------------------

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

public class XPathReadNS {

public static void main(String[] args) throws Exception {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse(new File("Berryz_Kobo_NS.xml"));

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();

//Namespace Specify
NamespaceContext nsContext = new NamespaceContextProvider("sinName" , "http://boris-chung.live.space.com");
xpath.setNamespaceContext(nsContext);

XPathExpression expr = xpath.compile("/sinName:berryz/sinName:singles/sinName:single/sinName:name/text()");

Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList textNameNodes = (NodeList) result;
for (int i = 0; i < textNameNodes.getLength(); i++) {
Node textNode = textNameNodes.item(i);
System.out.println("Single = "+textNode.getNodeValue());

}
}

}
--------------------------------------------------------------------------------------
ชื่อ prefix นั้นเราจะกำหนดเป็นอะไรก็ได้ (ตามใจเรา) แต่จะต้องใช้ให้ตรงกันกับใน XPath Query ด้วย จากตัวอย่างคือ sinName โดยใช้กับ Namespace “http://boris-chung.live.space.com” และสังเกตว่าใน XPath Query นั้นตอนที่ระบุชื่อ tag จะต้องใส่ prefix นำหน้าทุกตัว (อย่าลืมว่า childNode ของ Node ที่กำหนด Namespace นั้น ก็จะถือว่ามี Namespace นั้นไปด้วย)
เมื่อรันไฟล์ออกมาได้ผลลัพธ์เหมือนเดิมดังนี้

java_xml_xpath_4


สุดท้ายจะแถมเกี่ยวกับการใช้ XPath Query แบบที่กำหนดเงื่อนไขของ Attribute ให้ดูเป็นตัวอย่างเผื่อจะเอาไปใช้กัน สมมติว่าจะ Query สมาชิกที่ graduated ไปแล้ว (จากข้อมูล XML คือ “Ishimura Maiha”) ออกมา จะใช้ XPath Query ดังนี้
“/berryz/member[@graduated=’true’]/text()”
ให้ลองเอา XPath Query นี้ไปแทนในไฟล์ XPathRead.java ดู จะได้ผลลัพธ์ดังนี้

java_xml_xpath_5

การใช้ @ เป็นการอ้างอิงถึง Attribute ของตัว Node ซึ่งในที่นี้เราอ้างถึงเฉพาะ member ที่มีค่า graduated เป็น “true” เท่านั้น จึงได้ Ishimura Maiha ออกมา

When we implemented transactions using autowiring and TxManager in the spring config xml file, we ended up in having the well known org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here.

I was googling a bit on "No Hibernate Session bound to thread". Emphatically, I ended up with innumerous answers in several sites on the Internet. Springsource forum is not exception to this! Abundant conversations have been happening on this topic all around!!!

But there were a few best practices that I was able to compile from the chit-chats happening across the Internet. I thought of sharing the same here so that it would help some one some day in the near future!

  1. First and foremost, configure the transaction manager properly : Use @Transaction annotation near your code and have a transactionManager bean in your spring config file.
  2. when integration a transaction manager, do not use hibernate.current_session_context_class and hibernate.transaction_factory_class in the hibernate properties unless you have proper reasons to
  3. Never call sessionFactory.openSession()
  4. Use ApplicationContext rather than using BeanFactory
  5. Have single dao instances running across the Application
  6. Above all, most importantly, ensure that the current application context has the component scan for the beans where you have added the @transactional annotations. as per spring documentation's @ Trasactional usage guidelines,

only looks for @Transactional on beans in the same application context it is defined in. This means that, if you put in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services. See Section 15.2, “The DispatcherServlet” for more information.

Point # 6 was the culprit in our case and that was then resolved! So the lessson was You are likely to get "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here" if you do not adhere to any of the above pointers.
PArticularly, if you are going to have the applicationContext.xml with the TxManager and the servletname-servlet.xml with the component scan annotations, then you are more likely to get this "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here" exception since the TxManager's transaction holds good for the current application context only (which in this case does not have the bean definitions for the service or the daos where you have the @ Trasactional annotations)

If you find the information pretty helpful, I would really be happy if you would keep me posted via the comments form displayed under this article! If you had wanted some other information related to the same topic, I would suggest you to drop a note to me using the comments form for that would help me in getting back to you with the details you are in need of!

Ref : link

If you are using Spring to wrap a Hibernate SessionFactory and you are not using Spring-managed transactions, you may run into an issue. The reason is that Spring by default will wrap Hibernate’s SessionFactory implementation and delegate to its own transactional version. If you are just using the simple ThreadLocal-based session-per-request functionality, then when you attempt to open the Session, you will get an IllegalStateException thrown, with the error message "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here". This happens because Spring’s SessionFactoryUtils checks if the Session is bound to Spring’s transactional support, and by default throws an error if it is not.

The solution to this is to set the property



<property name="exposeTransactionAwareSessionFactory"><value>false</value></property>

in the Spring config. This will return the “raw” SessionFactory instead of the proxied one. A snippet of code from AbstractSessionFactoryBean shows where the check is done:

 
/**
* Wrap the given SessionFactory with a transaction-aware proxy, if demanded.
* @param rawSf the raw SessionFactory as built by buildSessionFactory()
* @return the SessionFactory reference to expose
* @see #buildSessionFactory()
* @see #getTransactionAwareSessionFactoryProxy
*/
protected SessionFactory wrapSessionFactoryIfNecessary(SessionFactory rawSf) {
if (isExposeTransactionAwareSessionFactory()) {
return getTransactionAwareSessionFactoryProxy(rawSf);
}
else {
return rawSf;
}
}

A sample Spring config is shown below.





<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="exposeTransactionAwareSessionFactory"><value>false</value></property>
<property name="annotatedPackages">
<list>
<value>uk.co.researchkitchen.hibernate</value>
</list>
</property>
<property name="annotatedClasses">
<list>
<value>uk.co.researchkitchen.hibernate.Product</value>
<value>uk.co.researchkitchen.hibernate.ProductDescription</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=create
hibernate.current_session_context_class=thread
</value>
</property>
</bean>

</beans>

Spring Intro Tutorial

Reading and Writing a Properties File

// Read properties file.
Properties properties = new Properties();
try {
properties.load(new FileInputStream("filename.properties"));
} catch (IOException e) { }

// Write properties file.
try {
properties.store(new FileOutputStream("filename.properties"), null);
} catch (IOException e) { }


To read java properties files from the classpath:

The properties files can be stored in the classpath. This way they can be put inside jar files and it’s really useful for web applications when the absolute location of the properties files is not known. When I tested this in an web application it didn’t work:

Properties properties = new Properties() ;
URL url = ClassLoader.getSystemResource("test.properties");
properties.load(new FileInputStream(new File(url.getFile())));

To read java properties files from the classpath in a web application:

The following example works to load the properties files in a web application. This snippet was tested on Tomcat 5.5. The ‘/’ represents the root of the class path. Otherwise the properties file location is considered relatively to “this” class (or to MyClass for the second example):

Properties properties = new Properties() ;
properties.load(this.getClass().getResourceAsStream("/seoimproved.properties"));

Similar example to use in a static context:

Properties properties = new Properties() ;
properties.load(MyClass.class.getResourceAsStream("/seoimproved.properties"));

To read java properties files from a specific location:

The properties files can be loaded from any location.

Properties properties = new Properties() ;
properties.load(new FileInputStream("C:\\tmp\\test.properties"));
In the J2EE application you can trust the class loader to find the properties file under this directory. For this you should code your application as:

String propFile = "propConfig.properties";
URL url = Thread.currentThread().getContextClassLoader().getResource(propFile);
Properties prop = new Properties();
prop.load( url.openStream() );


or

Properties prop = new Properties();
try
{
prop.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("hello.properties"));
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}

Ruby on Rails vs Java - Commercial

#1

#2
top