How to call a Oracle function from hibernate?

Hibernate Session provides a doWork() method that gives you direct access to java.sql.Connection. You can then create and use java.sql.CallableStatement to execute your function:

not parameter

session.doWork(new Work() {
  public void execute(Connection connection) throws SQLException {
    CallableStatement call = connection.prepareCall("{ call MYSCHEMA.MYFUNC() }");
    call.execute();
      }});

 

with parameter and return result

session.doWork(new Work() {
  public void execute(Connection connection) throws SQLException {
    CallableStatement call = connection.prepareCall("{ ? = call MYSCHEMA.MYFUNC(?,?) }");
    call.registerOutParameter( 1, Types.INTEGER ); // or whatever it is
    call.setLong(2, id);
    call.setLong(3, transId);
    call.execute();
    int result = call.getInt(1); // propagate this back to enclosing class 
 }});

reference : How to call a Oracle function from hibernate with return parameter?

, ,

ให้ความเห็น

DAO + Hibernate + Spring then!! java.sql.SQLException: Listener refused the connection with the following error: ORA-12519, TNS:no appropriate service handler found

I’m using Spring framework + Hibernate Oracle and DAO Pattern. I have over 1000 data for in a suite, When i use for loop for adding tests, I found Oracle error “ORA-12519, TNS:no appropriate service handler found” .Here some stack trace.

WARN  JDBCExceptionReporter - SQL Error: 0, SQLState: null
ERROR JDBCExceptionReporter - Listener refused the connection with the following error:
ORA-12519, TNS:no appropriate service handler found
The Connection descriptor used by the client was:
localhost:1522:orcl

 

Cause: Oracle doesn’t release connection resources as fast as you open/close them.

Resolve: use Thread.sleep()

For loop {

….

// do statement

// save , update , delete or other command

// after save , update , delete or other command ,sleep for oracle release connection

try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
  }

} // end for

Or Resolve : set Connection pool in proprety in hibernate configulation

hibernate.connection.pool_size=maximum number of pooled connections

 

here my ex. configulation

hibernate_conf_in_spring

, ,

ให้ความเห็น

Read Excel file with Java

Today a friend asked me to help guide him how to read data from a file excel wiht apache poi.
I said ‘ok’ and write this example code.

package org.my.test;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.junit.Test;

public class ReadXLS {
	public static void main(String[] args) {
		String path = "D:\\";
		String fileName = "exelfile.xls";
		String excelFile = path + fileName;
		InputStream inputStream = null;
		POIFSFileSystem fileSystem = null;

		try {
			inputStream = new FileInputStream(excelFile);
			fileSystem = new POIFSFileSystem(inputStream);

			HSSFWorkbook workBook = new HSSFWorkbook(fileSystem);
			HSSFSheet sheet = null;
			int sheetCounter = 0;
			while ((sheet = workBook.getSheetAt(sheetCounter)) != null) {
				System.out.println("############### SHEET ["
						+ workBook.getSheetName(sheetCounter)
						+ "] #################");
				Iterator rows = sheet.rowIterator();

				while (rows.hasNext()) {
					HSSFRow row = rows.next();

					// display row number in the console.
					System.out.println("Row No.: " + row.getRowNum());

					// once get a row its time to iterate through cells.
					Iterator cells = row.cellIterator();
					StringBuilder sb = new StringBuilder();
					while (cells.hasNext()) {
						HSSFCell cell = cells.next();

						sb.append("Cell No.: " + cell.getColumnIndex());

						/*
						 * Now we will get the cell type and display the values
						 * accordingly.
						 */
						switch (cell.getCellType()) {
						case HSSFCell.CELL_TYPE_NUMERIC: {

							// cell type numeric.
							sb.append("\tNumeric value: "
									+ cell.getNumericCellValue());

							break;
						}

						case HSSFCell.CELL_TYPE_STRING: {

							// cell type string.
							HSSFRichTextString richTextString = cell
									.getRichStringCellValue();

							sb.append("\tString value: "
									+ richTextString.getString());

							break;
						}

						default: {

							// types other than String and Numeric.
							sb.append("\tType not supported.");

							break;
						}

						}
						sb.append(" \n");
					}
					System.out.println(sb.toString());
				}
				System.out.println("############### END READ SHEET ["
						+ workBook.getSheetName(sheetCounter)
						+ "] #################");
				sheetCounter++;

				// if index is out of range break and exit reading xls file
				try {
					workBook.getSheetAt(sheetCounter);
				} catch (Exception e) {
					break;
				}

			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

, , ,

ให้ความเห็น

Basic Generic part 2

From the old code thank you rpgkan, but it is not a generic code so flexible that we can convert it to a generic version is better.

This’s old code version

package org.my.test;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class OldBatchObjectModel {
	/**
	 * for key set
	 */
	private Set idSet;
	/**
	 * map of value
	 */
	private Map batchDataMap;

	public OldBatchObjectModel() {
		idSet = new HashSet();
		batchDataMap = new HashMap();
	}

	/**
	 * put key and object value
	 *
	 * @param id
	 * @param obj
	 */
	public void putData(String id, Object obj) {
		idSet.add(id);
		Object item = batchDataMap.get(id);
		if (null == item) {
			batchDataMap.put(id, obj);
		}
	}

	/**
	 * get data from id
	 *
	 * @param id
	 * @return
	 */
	public Object getData(String id) {
		return batchDataMap.get(id);
	}

	/**
	 * get all key
	 *
	 * @return
	 */
	public Set getId() {
		return idSet;
	}

	/**
	 * remove value
	 *
	 * @param id
	 */
	public void removeDataById(String id) {
		batchDataMap.remove(id);
	}

	/**
	 * remove all data
	 */
	public void clear() {
		this.clearId();
		this.clearData();
	}

	/**
	 * remove all key set
	 */
	public void clearId() {
		idSet.clear();
	}

	/**
	 * remove all map value
	 */
	public void clearData() {
		batchDataMap.clear();
	}

	public int size() {
		return batchDataMap.size();
	}

}

 

Let’s see the test code.

 

package org.my.test;

import junit.framework.Assert;

import org.junit.Test;

public class OldBathObjectModelTest {
	@Test()
	public void testAdd() {
		OldBatchObjectModel ob = new OldBatchObjectModel();
		ob.putData("1", 2);
		ob.putData("2", "3");
		ob.putData("3", 2.0);

		if (ob.getData("1") instanceof Integer) {
			int x1 = ((Integer) ob.getData("1")).intValue();
			Assert.assertEquals(2, x1);
		}
		if (ob.getData("2") instanceof String) {
			String x2 = ((String) ob.getData("2")).toString();
			Assert.assertEquals("3", x2);
		}
		if (ob.getData("3") instanceof Double) {
			double x3 = ((Double) ob.getData("3")).doubleValue();
			Assert.assertEquals(2.0, x3);
		}
		Set ids = ob.getId();
		for (Iterator iterator = ids.iterator(); iterator.hasNext();) {
			String key = (String) iterator.next();
			if (ob.getData(key) instanceof Integer) {
				Assert.assertTrue(ob.getData(key) instanceof Integer);
			}else if (ob.getData(key)  instanceof String) {
				Assert.assertTrue(ob.getData(key) instanceof String);
			}
			if (ob.getData(key)  instanceof Double) {
				Assert.assertTrue(ob.getData(key) instanceof Double);
			}
		}
	}
}

You will see that it’s quite a lot of casting, and it does not help me much in terms of reuse, because you will need to check before pulling up to the time that it takes a data type that you want to do it. Let’s convert it to a generic version.

 

package org.my.test;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class NewBatchObjectModel  {
	/**
	 * for key set
	 */
	private Set idSet;
	/**
	 * map of value
	 */
	private Map batchDataMap;

	public NewBatchObjectModel() {
		idSet = new HashSet();
		batchDataMap = new HashMap();
	}

	/**
	 * put key and object value
	 *
	 * @param id
	 * @param obj
	 */
	public void putData(K id, V obj) {
		idSet.add(id);
		Object item = batchDataMap.get(id);
		if (null == item) {
			batchDataMap.put(id, obj);
		}
	}

	/**
	 * get data from id
	 *
	 * @param id
	 * @return
	 */
	public V getData(K id) {
		return batchDataMap.get(id);
	}

	/**
	 * get all key
	 *
	 * @return
	 */
	public Set getId() {
		return idSet;
	}

	/**
	 * remove value
	 *
	 * @param id
	 */
	public void removeDataById(K id) {
		batchDataMap.remove(id);
	}

	/**
	 * remove all data
	 */
	public void clear() {
		this.clearId();
		this.clearData();
	}

	/**
	 * remove all key set
	 */
	public void clearId() {
		idSet.clear();
	}

	/**
	 * remove all map value
	 */
	public void clearData() {
		batchDataMap.clear();
	}

	public int size() {
		return batchDataMap.size();
	}
	/**
	 * contain key
	 * @param id
	 * @return
	 */
	public boolean containsKey(K id){
		return this.idSet.contains(id);
	}
}

for String

 

package org.my.test;

public class StringBatchObjectModel extends NewBatchObjectModel{

}

for Integer

 

package org.my.test;

public class IntegerBatchObjectModel extends NewBatchObjectModel{

}

 

for Double

package org.my.test;

public class DoubleBatchObjectModel extends NewBatchObjectModel{

}

 

Test,Test,Test

package org.my.test;

import org.junit.Assert;
import org.junit.Test;

public class OldBathObjectModelTest {
	@Test()
	public void testInteger() {
		IntegerBatchObjectModel ob = new IntegerBatchObjectModel();
		ob.putData("1", 2);
		int x1 = ob.getData("1");
		Assert.assertTrue(2 == x1);
		Assert.assertTrue(ob.getData("1") instanceof Integer);
		Assert.assertTrue(ob.getData("1") == 2);
	}
	@Test()
	public void testString() {
		StringBatchObjectModel ob = new StringBatchObjectModel();
		ob.putData("1", "Some test string");
		String x1 = ob.getData("1");
		Assert.assertTrue("Some test string".equals(x1));
		Assert.assertTrue(ob.getData("1") instanceof String);
		Assert.assertTrue("Some test string".equals(ob.getData("1") ));
	}
	@Test()
	public void testDouble() {
		DoubleBatchObjectModel ob = new DoubleBatchObjectModel();
		ob.putData("1", 2.01);
		double x1 = ob.getData("1");
		Assert.assertTrue(2.01 == x1);
		Assert.assertTrue(ob.getData("1") instanceof Double);
		Assert.assertTrue(ob.getData("1") == 2.01);
	}
}

 

I hope you will continue to be applied to your code. ตกหลุมรัก

, ,

ให้ความเห็น

Basic Generic T

Here ,this’s example code for builder pattern.

AbstractBuilder.java

package org.my.generic.test;

public abstract class AbstractBuilder {
	public abstract T build(String line);
}

TableDirector.java

package org.my.generic.test;

public class TableDirector {
	public static void main(String[] args) {
		TableDirector director = new TableDirector();
		Table t1 = director.build("M|4");
		System.out.println("TYPE : " + t1.getType() + " | LEGs : "
				+ t1.getValue());
		Table t2 = director.build("W|8");
		System.out.println("TYPE : " + t2.getType() + " | LEGs : "
				+ t2.getValue());
	}

	private WoodTableBuilder woodTableBuilder = null;
	private MetalTabelBuilder metalTableBuilder = null;

	public TableDirector() {
		super();
		this.woodTableBuilder = new WoodTableBuilder();
		this.metalTableBuilder = new MetalTabelBuilder();
	}

	public Table build(String order) {
		Table table = null;
		if (order.startsWith("M")) {
			table = this.metalTableBuilder.build(order);
		}
		if (order.startsWith("W")) {
			table = this.woodTableBuilder.build(order);
		}
		return table;
	}

	class WoodTableBuilder extends AbstractBuilder
{

		@Override
		public Table build(String line) {
			String val[] = line.split("\\|");
			Table table = new Table();
			table.setType("WOOD");
			table.setValue(val[1]);
			return table;
		}
	}

	class MetalTabelBuilder extends AbstractBuilder
{ @Override public Table build(String line) { String val[] = line.split("\\|"); Table table = new Table(); table.setType("METAL"); table.setValue(val[1]); return table; } } class Table { private String type; private String value; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } }

,

ให้ความเห็น

เขียน test งานขำ ๆ กับ Spring + jUnit4

เรื่องมันมีอยู่ว่า..เดิมเป็นคนเขียนงานไม่ค่อยเขียน test ก็ด้นสดกันไป เขียน test แบบไหนนะหรอ? ก็เขียนใน main method ไง แทรกไว้ใน class นั้นละ แบบนี้

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
	private static int YEAR = 3000;
	private static int MONTH = 12;
	private static int DATE = 31;
	private static int HOUR = 24;
	private static int MINUTE = 60;
	private static int SECOND = 60;
	public static void test() {
		int time[][][] = new int[HOUR][MINUTE][SECOND];
		for (int i = 0; i < time.length; i++) {
			for (int j = 0; j < time[i].length; j++) {
				for (int k = 0; k < time[i][j].length; k++) {
					// System.out.println(i + " : " + j + " : " + k);
					time[i][j][k] = 0;
				}
			}
		}
		int counter = 0;
		System.out.println("time 1:00:00 : " + time[1][0][0]);
		// set time 1:30:20 to counter 1
		time[1][30][20] += 1;
		time[1][30][20] += 1;
		time[1][31][20] += 1;
		// count between time 1:30:00 - 1:30:59
		for (int i = 0; i < time[1][30].length; i++) {
			counter += time[1][30][i];
		}
		System.out.println("count between time 1:31:00 - 1:30:59 : " + counter);
		// count between time 1:31:00 - 1:31:59
		counter = 0;
		for (int i = 0; i < time[1][31].length; i++) {
			counter += time[1][31][i];
		}
		System.out.println("count between time 1:31:00 - 1:31:59 : " + counter);
		// time 1:00:00
		time[1][0][0] += 1;
		// time 1:03:24
		time[1][3][24] += 1;
		// time 2:00:23
		time[2][0][23] += 1;

		// count between time 1:00:00 - 3:00:00
		counter = 0;

		for (int i = 0; i < SECOND; i++) {
			for (int j = 0; j < MINUTE; j++) {
				for (int h = 1; h <= 3; h++) {
					counter += time[h][j][i];
				}
			}

		}
		System.out.println("count between time 1:00:00 - 3:00:00 : " + counter);

	}
}

 

ผลที่ได้นะหรอ ก็รันได้ราบรื่นปรกตินะซิแล้วไปตายเอาดาบหน้า :P หลังจากได้อ่าน Test Driven Development ที่พี่ roofimon เขียนไว้ หลัง ๆ เลยเปลี่ยนตัวเองใหม่สาบานว่าจะเขียน 1 test class ต่อ class ที่เขียนขึ้นหนึ่งตัว ( กรณีขยันสุด ๆ นะ ) ผลที่ได้นะหรอเขียนตั้งแต่ test domain class ยัน test service class กันเลยทีเดียว เดี๋ยวจะหาว่าโม้ ขั้นตอนเขียน JUnit4 ( ใช้ version 4 มันง่ายเพราะมี annotation ) เขียนยังงี้ครับ

import junit.framework.Assert;

import org.junit.Test;

public class TestEventDomain {
	private static int YEAR = 3000;
	private static int MONTH = 12;
	private static int DATE = 31;
	private static int HOUR = 24;
	private static int MINUTE = 60;
	private static int SECOND = 60;

	@Test
	public void testHour() {
		int time[][][] = new int[HOUR][MINUTE][SECOND];
		for (int i = 0; i < time.length; i++) {
			for (int j = 0; j < time[i].length; j++) {
				for (int k = 0; k < time[i][j].length; k++) {
					// System.out.println(i + " : " + j + " : " + k);
					time[i][j][k] = 0;
				}
			}
		}
		int counter = 0;
		int m = 0;
		System.out.println("time 1:00:00 : " + time[1][0][0]);
		// set time 1:30:20 to counter 1
		time[1][30][20] += 1;
		time[1][30][20] += 1;
		time[1][31][20] += 1;
		Assert.assertEquals(2, time[1][30][20]);
		Assert.assertEquals(1, time[1][31][20]);
		// // count between time 1:30:00 - 1:30:59
		for (int i = 0; i < time[1][30].length; i++) {
			counter += time[1][30][i];
		}
		Assert.assertEquals(2, counter);
		System.out.println("count between time 1:31:00 - 1:30:59 : " + counter);
		// // count between time 1:31:00 - 1:31:59
		counter = 0;
		for (int i = 0; i < time[1][31].length; i++) {
			counter += time[1][31][i];
		}
		Assert.assertEquals(1, counter);
		System.out.println("count between time 1:31:00 - 1:31:59 : " + counter);
		// time 1:00:00
		time[1][0][0] += 1;
		// time 1:03:24
		time[1][3][24] += 1;
		// time 2:00:23
		time[2][0][23] += 1;

		// count between time 1:00:00 - 3:00:00
		counter = 0;

		for (int i = 0; i < SECOND; i++) {
			for (int j = 0; j < MINUTE; j++) {
				for (int h = 1; h <= 3; h++) {
					counter += time[h][j][i];
				}
			}

		}
		Assert.assertEquals(6, counter);
		System.out.println("count between time 1:00:00 - 3:00:00 : " + counter);

	}
}

 

แค่ประกาศบนหัวเป็น annotation @Test ครับแล้วรันแบบ JUnit Test บน eclipse มันก็รันแล้วรอดูผลบน console ได้ปกติ แล้วมันเอามาใช้กับ spring ยังไงละ ปกติถ้าเราเขียน spring แบบ basic เราจะมี configulation ที่เป็น file xml หนึ่งตัวใช่ไหมละ ดัง code ข้างล่างนี้ราจะเรียกมันผ่าน main method โดย new ClassPathXmlApplicationContext แล้วเราก็ใส่ file configulation นั้นลงไปเราจะได้ instance ของ application context มาเพื่อจะเรียก bean แล้วดำเนินการต่อไป

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.my.scheduler.quartz.service.JobService;

public class SpringTest {
	private static ApplicationContext ctx;

	public static void main(String[] args) {
		ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		JobService readFileJobService = (JobService) ctx.getBean("readFileJobService");
		try {
			readFileJobService.doJob();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

 

ที่นี่ถ้าจะเขียนเพื่อดึง bean จาก spring มา test แบบ junit ทำยังไง? spring เตรียมมาให้แล้วครับด้วย class SpringJUnit4ClassRunner อยู่ใน package org.springframework.test.context.junit4 วิธีการก็ง่าย ๆ ใช้ annotation @RunWith กับ @ContextConfiguration และ @Resource ช่วยเข้าไปเท่านี้เรียบร้อยดังตัวอย่าง

import java.io.FileNotFoundException;

import javax.annotation.Resource;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import org.my.scheduler.quartz.service.JobService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
		"classpath*:/applicationContext-common-hibernate.xml",
		"classpath*:/applicationContext-log-aop.xml",
		"classpath*:/applicationContext-dao.xml",
		"classpath*:/applicationContext-aop.xml",
		"classpath*:/applicationContext-job.xml" })
public class ReadFileJobWorkerImplTest {
	@Resource(name = "readFileJobService")
	JobService readFileJobService;

	@Test
	public void loadTest() {
		try {
			readFileJobService.doJob();

		} catch (NullPointerException e) {
			// if some path is null or empty can except null pointer exception
			Assert.assertEquals(true, (e instanceof NullPointerException));
		} catch (FileNotFoundException e) {
			Assert.assertEquals(true, (e instanceof FileNotFoundException));
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}

 

ลองเอาไปเล่นกันดูครับ :P

, , , ,

ให้ความเห็น

เคยเขียน Thread ไหม?

ว่าจะเขียน blog นี้ตั้งแต่สองอาทิตย์ก่อนแต่งานมันเยอะ แลบลิ้น วันนี้ว่างนิด ๆ เลยเกงานมาเขียน blog ซะหน่อย “เคยเขียน Thread ไหม?” มันก็เขียนยังงี้ครับ

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.junit.Test;

public class ThreadTest {

	@Test
	public void testThread() {
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("normal thread : "
						+ Thread.currentThread().getName());
				sleep(1000);
			}
		});
		thread.start();
	}

	private static void sleep(int value) {
		try {
			Thread.sleep(value);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

 

อันนี้คือการเขียน Thread โดยใส่ object runable เราอาจจะเรียก worker ก็ได้ เสร็จแล้วเราก็สั่งให้มันทำงานด้วย method start มันก็จะวิ่งเข้าไปทำงานใน statement ทีเขียนไว้ครับ หลังจากเรารู้วิธีการเขียน Thread แบบง่าย ๆ แล้วเรามาดูเรื่องถัดไปดีกว่า เพราะคำถามถัดมาที่ผมได้รับ “ถ้าเกิดมันมีหลาย ๆ file มันจะทันไหม?” แปลว่ากระบวนการทำงานของเราไม่ได้มีแค่งาน ๆ เดียวครับ มันอาจจะพร้อม ๆ กันต้องทำงานหลาย ๆ งานก็ได้ ทำไงดีละ?? ผมก็มองไปที่ Thread Pool ก่อน โชคดีผมเขียน java 1.6 ชีวิตมันเลยง่ายขึ้นมาหน่อยไม่ต้องเขียนตัวจัดการ pool เองมันก็มี class ที่ใช้จัดการเบื้องต้นมาให้เสร็จสรรพแล้ว :D

มันคือ class ไหนเหรอ?? ครับพระเอกของเรามันคือ class Executors,ExecutorService ครับลองดูวิธีการเขียนกันดีกว่า

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.junit.Test;

public class ThreadTest {

	@Test
	public void testFixThreadPool() {
		ExecutorService es = Executors.newFixedThreadPool(5);
		long start = System.currentTimeMillis();
		Runnable task = new Runnable() {

			@Override
			public void run() {
				System.out.println("fix thread : "
						+ Thread.currentThread().getName());
				sleep(1000);
			}
		};

		for (int i = 0; i < 10; i++) {
			es.execute(task);
			sleep(500); // 1
		}
		es.shutdown();
		long stop = System.currentTimeMillis();
		System.out.println("fix thread took: " + (stop - start));
	}

	@Test
	public void testThreadCachePool() {
		ExecutorService es = Executors.newCachedThreadPool();
		long start = System.currentTimeMillis();
		Runnable task = new Runnable() {

			@Override
			public void run() {
				System.out.println("cache thread : "
						+ Thread.currentThread().getName());
				sleep(1000);
			}
		};

		for (int i = 0; i < 10; i++) {
			es.execute(task);
			sleep(500); // 1
		}
		es.shutdown();
		long stop = System.currentTimeMillis();
		System.out.println("cache thread took: " + (stop - start));
	}

	@Test
	public void testSingleThread() {
		ExecutorService ec = Executors.newSingleThreadExecutor();
		long start = System.currentTimeMillis();
		Runnable task = new Runnable() {

			@Override
			public void run() {
				System.out.println("single thread : "
						+ Thread.currentThread().getName());
				sleep(1000);
			}
		};

		for (int i = 0; i < 10; i++) {
			ec.execute(task);
		}

		ec.shutdown();
		waitTenSeconds(ec);
		long stop = System.currentTimeMillis();
		System.out.println("single thread took: " + (stop - start));
	}

	private static void waitTenSeconds(ExecutorService ec) {
		try {
			ec.awaitTermination(10, TimeUnit.SECONDS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	private static void sleep(int value) {
		try {
			Thread.sleep(value);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

เราจะเห็นได้ว่า Executors.newSingleThreadExecutor() นั้นทำงานช้าเพราะมันต้องเข้าไปทำงานที่ Thread เดียวกัน ตรงกันข้าม Executors.newCachedThreadPool() กลับทำงานเร็วกว่าใน loop เราจะสร้าง Thread เท่าที่ต้องการและไม่ต้องรอให้ Thread ก่อนหน้าทำงานเสร็จเหมือน SingleThread ครับ CachedThreadPool เนี่ยจะเป็นเช่นเดียวกับ FixedThreadPool ครับแต่ FixedThreadPool เราสามารถจำกัดจำนวนของ Thread ได้ครับการทำงานของมันจะ reues Thread ที่มีอยู่นำมาใช้งาน เป็นไงครับ java กับ thread pool ง่ายใช่มะ?

, , ,

ให้ความเห็น

Java with Quartz 2.0.1

วันก่อนหลังจากย้ายงานมาจากที่ทำงานเดิมมาทำที่ใหม่ ได้โจทย์มาว่าคุณลูกค้าต้องการยังงี้ ๆ เราก็อ้อต้องการให้มีตัวกวาดไฟล์มาทำงานทุก ๆ ช่วงเวลา และในหนึ่งช่วงเวลาก็มีหลายงานที่ต้องทำเสียเหลือเกิน เราก็นึกถึง Quartz ขึ้นมาทันทีตัวหากินเลยนะ ยิ้ม เลยได้เวลากลับไปดู Quartz ซะหน่อย home page เขาก็บอกว่า release ล่าสุดเขา 2.0.1 นะเคยแต่ใช้ตัวเก่า 1.6+ ไม่เคยใช้ 2+ มาก่อนเลยโหลดมาลองใช้กัน โอ้วแตกต่างจากวิธีเขียนเดิมไม่มาก แต่ถ้าไม่ได้อ่าน doc อาจจะงงเล็กน้อย ลองเข้าไปดูที่ What’s New In Quartz Scheduler 2.0 เกริ่นมาเยอะลองไปดูวิธีเขียนกันดีกว่า

สร้าง TriggerJob ก่อน

package org.my.quartz;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;

public class HelloTriggerJob implements Job {

	@Override
	public void execute(JobExecutionContext context)
			throws JobExecutionException {
		JobKey jobKey = context.getJobDetail().getKey();
		System.out.println("HelloJob says: " + jobKey + " executing at "
				+ new Date());
	}

}

แล้วก็สร้าง CronJob

package org.my.quartz;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;

public class HelloCronJob implements Job {

	@Override
	public void execute(JobExecutionContext context)
			throws JobExecutionException {
		JobKey jobKey = context.getJobDetail().getKey();
		System.out.println("HelloCronJob says: " + jobKey
				+ " this time is " + new Date());

	}

}

พอได้ทั้ง cron และ trigger แล้วเรามาลองสร้าง Quartz Scheduler เพื่อจะใช้ปลุก job ทั้งสองแบบมาทำงานกัน

package org.my.quartz;

import java.text.ParseException;
import java.util.Date;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerMetaData;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

public class MyQuartzScheduler {

	SchedulerFactory sf;

	Scheduler sched;

	private void createCronTrigger() throws SchedulerException, ParseException {
		// job will run every 20 seconds
		JobDetail job = JobBuilder.newJob(HelloCronJob.class).withIdentity(
				"cronjob", "cronjobgroup1").build();
		CronScheduleBuilder cronBuilder = CronScheduleBuilder
				.cronSchedule("0/20 * * * * ?");

		// CronTrigger the job to run on the every 20 seconds
		CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(
				"crontrigger", "crontriggergroup1").withSchedule(cronBuilder)
				.build();

		// Tell quartz to schedule the job using our crontrigger
		Date ft = sched.scheduleJob(job, cronTrigger);
		System.out.println(job.getKey() + " has been scheduled to run at: "
				+ ft + " and repeat based on expression: "
				+ cronTrigger.getCronExpression());
	}

	private void createTrigger() throws SchedulerException {
		// computer a time that is on the next round minute
		Date runTime = DateBuilder.evenMinuteDate(new Date());

		System.out.println("------- Scheduling Job  -------------------");

		// define the job and tie it to our HelloTriggerJob class

		JobDetail job = JobBuilder.newJob(HelloTriggerJob.class).withIdentity(
				"triggerjob", "triggerjobgroup1").build();

		// Trigger the job to run on the next round minute
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger",
				"triggergroup1").startAt(runTime).build();

		// Tell quartz to schedule the job using our trigger
		sched.scheduleJob(job, trigger);
		System.out.println(job.getKey() + " will run at: " + runTime);

	}

	public void init() throws SchedulerException, ParseException {
		System.out.println("------- Initializing ----------------------");
		sf = new StdSchedulerFactory();
		sched = sf.getScheduler();
		System.out.println("------- Initialization Complete -----------");

		createTrigger();

		createCronTrigger();

		// Start up the scheduler (nothing can actually run until the
		// scheduler has been started)
		sched.start();

		System.out.println("------- Started Scheduler -----------------");

		// wait long enough so that the scheduler as an opportunity to
		// run the job!
		System.out.println("------- Waiting 65 seconds... -------------");
		try {
			// wait 65 seconds to show job
			Thread.sleep(65L * 1000L);
			// executing...
		} catch (Exception e) {
		}

		// shut down the scheduler
		System.out.println("------- Shutting Down ---------------------");
		sched.shutdown(true);
		System.out.println("------- Shutdown Complete -----------------");

		SchedulerMetaData metaData = sched.getMetaData();
		System.out.println("Executed " + metaData.getNumberOfJobsExecuted()
				+ " jobs.");
	}

	public static void main(String[] args) {
		try {
			new MyQuartzScheduler().init();
		} catch (SchedulerException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}
}

ลองทดสอบรันกันดูนะครับ :)

, ,

ให้ความเห็น

เขียน Client–Server เป็นไหม???

เขียน Client – Server เป็นไหม? คำถามหนึ่งประโยคออกมาจากปากผู้สัมภาษณ์ผม ทำให้นึกย้อนกลับไปว่าเคยเขียนบ้างไหม? ต้องเคยซิ … แล้วมันเขียนยังไงละ?

เราเริ่มกันที่การเขียน code ฝั่ง server ก่อนละกัน

Server แบบ Java Code

แบบแรกเขียนใช้ DataOutputStream , DataInputStream

package com.my.test.socket;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest {
	private static int port = 4444;

	public static void main(String[] args) {
		ServerSocket server;
		try {
			server = new ServerSocket(port);
			Socket socketAccept;
			while (true) {
				socketAccept = server.accept();
				System.out.println("Accept from "
						+ socketAccept.getInetAddress().getHostName());
				DataOutputStream output = new DataOutputStream(socketAccept.getOutputStream());
				DataInputStream input = new DataInputStream(socketAccept.getInputStream());

				String str = input.readLine();
				System.out.println(str);
				output.writeBytes("Hi,I'm fine.\n");
				output.flush();
				System.out.println("response successfully.");
				output.close();
				socketAccept.close();
			}
		} catch (IOException e) {
			System.err.println(e.toString());
		}
	}
}

แบบที่สองขียนใช้ PrintStream, BufferedReader

package com.my.test.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest {
	private static int port = 4444;

	public static void main(String[] args) {
		ServerSocket server;
		try {
			server = new ServerSocket(port);
			Socket socketAccept;
			while (true) {
				socketAccept = server.accept();
				System.out.println("Accept from "
						+ socketAccept.getInetAddress().getHostName());

				PrintStream output = new PrintStream(socketAccept.getOutputStream());
				BufferedReader input = new BufferedReader(
						new InputStreamReader(socketAccept.getInputStream()));

				String str = input.readLine();
				System.out.println(str);
				output.print("Hi,I'm fine.\n");
				output.flush();
				System.out.println("response successfully.");
				output.close();
				socketAccept.close();
			}
		} catch (IOException e) {
			System.err.println(e.toString());
		}
	}
}

แล้ว Client ละ? ก็เขียนทำนองเดียวกันครับแบบนี้

package com.my.test.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class Client {
	public static void main(String[] args) throws InterruptedException {
		try {
			Socket socket = new Socket("localhost", 4444);
			PrintWriter writer = new PrintWriter(socket.getOutputStream());
			writer.print("Hi,How are you?\n");
			writer.flush();

			BufferedReader reader = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			String s = null;
			while ((s = reader.readLine()) != null) {
				System.out.println(s);
			}
			socket.close();
		} catch (IOException e) {
			System.err.println(e.toString());
		}
	}

}

ลอง run โปรแกรมดูนะครับ run server ก่อนแล้วค่อย run client

ที่นี่มาดู code แบบ groovy บ้าง

Server แบบ groovy

package com.my.socket

import java.net.ServerSocket

def server = new ServerSocket(4444)

while(true) {
	server.accept { socket ->
		println "processing new connection..."
		socket.withStreams { input, output ->
			def reader = input.newReader()
			def buffer = reader.readLine()
			println "server received: $buffer"
			now = new Date()
			output << "echo-response($now): Hi,I'm fine.\n"
		}
		println "processing/thread complete."
	}
}

Client แบบ groovy

package com.my.socket

s = new Socket("localhost", 4444);
s.withStreams { input, output ->
  output << "Hi,How are you?\n"
  buffer = input.newReader().readLine()
  println "response = $buffer"
}

เขียนสั้นกว่า java แต่ผลการทำงานเหมือน ๆ กันเลย >_<” สั้นเกิ๊น

, ,

ให้ความเห็น

5 สิ่งที่คุณยังไม่รู้เกี่ยวกับ Java performance monitoring ตอนที่ 1

 

เห็นเป็นบทความที่ดีเลยเก็บไว้อ่านซักหน่อย ต้นฉบับอยู่ที่ developerWorks เดี๋ยวจะลอง ๆ อ่านดู  5 things you didn’t know about … Java performance monitoring, Part 1

จะลองอ่านแล้วมาขยายความดูในโอกาสต่อไป

,

2 ความเห็น

Follow

Get every new post delivered to your Inbox.