顯示具有 java 標籤的文章。 顯示所有文章
顯示具有 java 標籤的文章。 顯示所有文章

2012年11月15日 星期四

Google Cloud SQL

對於很多用慣retional DB的使用者來說,Google Cloud SQL DB的推出或許是個福音
目前的Cloud SQL以MySQL 5.5為主,提供

-高可靠度與高可用度,自動幫開發者複製資料
-JAVA的JDBC與Python的DB-API供使用
-可直接與Appengine整合

目前Google 提供free trail(至2013 Q1),可在建立instance的時候選擇size D0,輸入所要建立的instance name,這裡建議取短一點以方便後面呼叫(id:instance name)使用


建立好之後,畫面轉至該instance的Dashboard,
而相關table的建立與管理可透過SQL prompt or the command line tool
SQL Prompt為一個web版的sql consloe,下圖示範建立一Database guestbook



另外建立table person並insertㄧ筆資料,最後select所有person得資料如下:

建立好資料庫相關表格後,就可以著手進行與Google App Engine的整合了
官方附了一個簡單的guestbook範例的jsp頁面+servlet code與web.xml的設定供參考

Using Google Cloud SQL with App Engine Java SDK
https://developers.google.com/appengine/docs/java/cloud-sql/developers-guide


連線到DB需依照下列步驟:
1.import google appengine提供的JDBC Driver

import com.google.appengine.api.rdbms.AppEngineDriver;

2.連線到資料庫(jdbc:)

 DriverManager.registerDriver(new AppEngineDriver());
 c = DriverManager.getConnection("jdbc:google:rdbms://instance_name/guestbook");
完成後就可以把專案deploy到Google App Engine上查看結果了



2012年3月11日 星期日

Android ExpandableListActivity and SimpleCursorTreeAdapter

在Android app的開發中,若想實現點擊listview中的某個item則展開下面的子list,可利用ExpandableListActivity來達到此目的,官方的範例如下: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList1.html 而此list activity對應到的adapter可使用SimpleExpandableListAdapter或者extends BaseExpandableListAdapter作彈性的使用,說明如下:
 
// 使用SimpleExpandableListAdapter顯示ExpandableListView
         
      
        SimpleExpandableListAdapter adapter = new SimpleExpandableListAdapter(
                this,//指定Context
                groups,//第一層集合
                R.layout.groups,//第一層所使用的layout
                new String[] { "group" },//fromto,就是map中的key,指定要顯示的對象
                new int[] { R.id.group }, //顯示在groups中的id
                childs,//第二層集合
                R.layout.child,//第一層所使用的layout
                new String[] { "child" },//fromto,就是map中的key,指定要顯示的對象 
                new int[] { R.id.child });
        setListAdapter(adapter);
而若第一二層都想使用cursor為基礎之資料的話,則可extends SimpleCursorTreeAdapter來實現這個功能,底下附上最近部分片段
 private class MyExpandableListAdapter extends SimpleCursorTreeAdapter {

  public MyExpandableListAdapter(Cursor cursor, Context context,
    int groupLayout, int childLayout, String[] groupFrom,
    int[] groupTo, String[] childrenFrom, int[] childrenTo) {
   super(context, cursor, groupLayout, groupFrom, groupTo,
     childLayout, childrenFrom, childrenTo);
  }

  /*
   *取得第一層之cursor後,return該cursor對應之下一層資料的資料查詢結果
   */
  @Override
  protected Cursor getChildrenCursor(Cursor arg0) {
   String[] queryArgs = new String[1];
   queryArgs[0] = arg0.getString(arg0.getColumnIndex("_id"));
   
   return getOrderByTicket("order_id=?", queryArgs);

  }
 }
實作完自訂的adapter後,則可於使用setListAdapter設定該adapter
//取得第一層之cursor
parentCursor=db.getAll();
//宣告使用的adapter
 MyExpandableListAdapter adapter = 
            new MyExpandableListAdapter(
     parentCursor,//第一層使用之cursor
                                        this,//context
     R.layout.parentLayout,// parent layout
     R.layout.childLyout,// child layout
                                        new String[] { "table_num","customer_count", "price" },//parent cusror column
                                        new int[] {R.id.textView1, R.id.textView2, R.id.textView3 },//parent layout mapping id
     new String[] { "name", "count" },//child cursor column
                                        new int[] {R.id.textView1, R.id.textView2 });//child layout mapping id

    ExpandableListView expListView = getExpandableListView();
//如果不想顯示indicator可將groupindicator設成null  
    expListView.setGroupIndicator(null);
 //指定adapter
   setListAdapter(adapter);

Android SimpleCursorAdapter

最近想作個小工具放到market分享,中途遇到了listview的item要與DB的CRUD結合,
所以對於要如何在listview中取得SQLite中cursor對應的id感到困擾,所幸在survey了
一下相關的問題後,找到了android提供的SimpleCursorAdapter,該adapter的好處在於可以將db查詢回傳的Cursor直接使用,如此可方便開發者在Listview的item click listener中進行物件的操作
SimpleCursorAdapter的建構子如下:
SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to)
更多資訊可參考http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html

foodCursor = getFoodCursor();//取得sqlite Cursor
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
this,
 R.layout.mylistview2,//指定的layout
foodCursor,////取得sqlite Cursor
 new String[] { "name", "price", "category" },//所要顯示的db欄位,這裡要顯示的為name,price,category
new int[] { R.id.textView1, R.id.textView2, R.id.textView3 }//對應的layout id
);
而另外一個使用SimpleCursorAdapter的好處在於一般的apadter在更新資料後,往往要搭配dapter的notifyDataSetChanged()通知UI畫面重新更新,而直接使用SimpleCursorAdapter僅需要使用Cursor.requery()即可更新UI,非常的方便

http://developer.android.com/reference/android/widget/CursorAdapter.html

2011年7月10日 星期日

Java REST Web Service(1)

相對於傳統的Web Services是以SOAP訊息為主,REST逐漸竄升為Open Service主流的服務提供方式,REST(REpresentational State Transfer)以資源導向來提供服務,最早出現在http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm,主要提供使用者以Http method來對資源進行操作(CRUD),如使用
-post method用來進行資源之新增
-delete method用來進行資源之刪除
-get method用來取得資源
-put method用來更新(or上傳)資源

Java提供了JAX-RS與Jersey來提供Java語言進行REST服務的開發與使用
Jersey: http://wikis.sun.com/display/Jersey/Main
http://www.vogella.de/articles/REST/article.html


import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

@Path("/hello")
public class HelloService {
@GET//指定http method
@Produces("text/plain")//@Produces指定server回覆的response type
public String getMessage(){
return "Hello";
}
}

如此當使用者針對http://url/hello進行get method進行存取即可得到server回應的hello
servlet 2.x web.xml設定如下


Jersey Web Application
com.sun.jersey.spi.container.servlet.ServletContainer

javax.ws.rs.Application
tw.andy.rest



Jersey Web Application
/rest/*


init-param裡面須指定RESTful服務之package以供web server尋找request相對應之class
進階的檔案上傳功能則可使用jersey library來協助,文件如下:
http://aruld.info/handling-multiparts-in-restful-applications-using-jersey/

2011年1月23日 星期日

Javamail over SSL and TLS

最近因為工作得需要,把原本的javamail連線改為ssl,就順便把遭遇到的問題及解法附上來
網路上最多的javamail ssl範例為gmail的寄信範例,其中又分為SSL與TLS,GMAIL的SSL範例參考如下
http://www.mkyong.com/java/javamail-api-sending-email-via-gmail-smtp-example/



import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class JavaMailApp2
{
public static void main( String[] args )
{
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");

Session session = Session.getDefaultInstance(props,
new javax.mail.Authenticator()
{
protected PasswordAuthentication getPasswordAuthentication()
{ return new PasswordAuthentication("username","password"); }
});

try {

Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("from@no-spam.com"));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse("to@no-spam.com"));
message.setSubject("Testing Subject");
message.setText("test msg");

Transport.send(message);

System.out.println("Done");

} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
}

而在TLS的傳輸上可以參考http://www.coderanch.com/t/471285/sockets/java/Confusion-over-SSL-TLS-sending 的範例,這裡附上hotmail與gmail的設定
Hotmail:

Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
Properties props = new Properties();
props.put("mail.host","smtp.live.com");
props.put("mail.smtp.port", 587);
props.put("mail.smtp.auth", "true");

Gmail:

Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
Properties props = new Properties();
props.put("mail.host","smtp.gmail.com");
props.put("mail.smtp.port", 587);
props.put("mail.smtp.auth", "true");

上面的設定也實際測試過驗證無誤,此類連線為server端設定以TLS加密傳送純文字格式密碼做為驗證(Plaintext Authentication over TLS),如下圖:


不過特別要注意的是雖然爬完網路上的文章,一開始依然沒辦法成功的建立連線,出現下列的exception
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
原因為寄信程式得client端並未找到信任server端的truststore,是故跟mail server管理者取得.cer檔的憑證後,使用keytool將該cer檔封裝到jks的truststore conntainer中,並且於程式碼指定truststore位置

System.setProperty("javax.net.ssl.trustStore","C:/trustStore.jks");

如此才成功的使用TLS連線發送信件

2010年7月28日 星期三

[Note]Maven


最近因為想開發android與google storage結合的application,於是認真的研究了一下相關的資料
一開始選擇自己硬幹從google storage的authrization開始實做起,搭配apache httpclient 4.x存取google storage的RESTful API,結果目前一直收到403 forbidden,只好轉向查看網路上有沒有別人開發的project
搜尋了一下,其實因應雲端的到來,開始有人針對所有的cloud去實做存取的api,其中自己找到比較大的就屬
jclouddasein-cloud 這兩個project
dasein-cloud 提供user類似JDBC的概念使得開發者可以略過各家Cloud Provider需實做的繁瑣的API介接,供使用者得以使用統一的語法對各家cloud進行操作
而jcloud開發理念也如此,不過針對我所需要的google storage目前則尚在開發中,開發者建議我直接使用目前的snapshot版本,也因此讓我接觸到使用maven build自己的jar
簡單紀錄一下常用的指令
mvn compile(compile project)
mvn clean (清除原本建立的紀錄)
mvn package (build成jar)
而與eclipse的整合可看eclipse-plugin
Maven with Eclipse 3.5 (Gallileo)

待續

2010年7月22日 星期四

[Note] Google Storage API 開發二三事

Google Storage API
GS 提供了RESTful的介面供開發者使用

GET Service—lists all of the buckets that you own.
PUT Bucket—creates a bucket and changes the permissions on a bucket.
GET Bucket—lists the contents of a bucket or retrieves the ACLs that are applied to a bucket.
DELETE Bucket—deletes an empty bucket.
GET Object—downloads an object or retrieves the ACLs that are applied to an object.
PUT Object—uploads an object or applies new ACLs to an object.
DELETE Object—deletes an object.
HEAD Object—lists the metadata for an object.
POST Object—uploads an object by using HTML forms.

而目前網路上提供的資源如下:

Boto: Python interface to GS and S3
CloudBerry: Windows的檔案管理工具
Cyberduck : Mac上的browser
Dasein Cloud: open source Java API(如JDBC)
Data Nucleus : JDO/JPA plug in
Gladinet: maps network drives and provides AFS suppor
gstorea :Ruby client library
SharpGsa C# library

時間格式的要求上 google storage API要求的時間格式為UTC,時間格式處理如下:

SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ssz", new Locale("US"));
Calendar cal = Calendar.getInstance(new SimpleTimeZone(0, "GMT"));

format.setCalendar(cal);
return format.format(new Date());


而Google Storage在每個request都需使用auth
Signature = Base64-Encoding-Of(HMAC-SHA1(UTF-8-Encoding-Of(YourGoogleStorageSecretKey, MessageToBeSigned)))

public static String makeHMACSHA(String msg) {
byte[] hmac = new byte[msg.length()];
SecureRandom sr = new SecureRandom();
byte[] keyBytes = new byte[20];
sr.nextBytes(keyBytes);

try {
//將google提供的Secret key以UTF-8的編碼取出
SecretKey sk = new SecretKeySpec(GS_SK.getBytes("utf-8"),
"HmacSHA1");
//使用HMAC-SHA1
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(sk);
//傳入UTF-8編碼的訊息
mac.update(msg.getBytes("utf-8"));
hmac = mac.doFinal();

} catch (Exception e) {
e.printStackTrace();
} finally {
//回傳Base64編碼過得HMAC-SHA1值
return new String(Base64.encodeBase64(hmac));

}

}

2010年5月24日 星期一

Singleton notes

Singleton是近代有名的Design Pattern,以下介紹各種實做的approach
-Enum approach
Java SE 1.5後多了enum的型態,enum沒有可以access的constructor,不能被extend,根據"Effective Java"指出 single-element enum是最佳實作singleton的方式

public enum Singleton{
INSTANCE;
}

-static initializer

public final class Singleton {

private static final Singleton instance = new Singleton();
//一開始即做靜態的初始
private Singleton() {
//初始化的欄位
}

public static Singleton getInstance() {
return instance;
}
}

-Synchonized approach

public final class Singleton {

private static final Singleton instance = null; //宣告為null

private Singleton() {
//初始化的欄位
}

public static synchronized Singleton getInstance() {
return instance;//確保getinstance()有synchronized避免race condition
}
}

x Boken Singleton-Double checked locking
此問題詳細介紹如下:
http://en.wikipedia.org/wiki/Double-checked_locking

public class Singleton {

private static final Singleton instance = null; //宣告為null

public static Singleton getInstance() {

if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

-Lazy initialization
1.initialize-on-demand holder class idiom

public final class Singleton {

private Singleton() {
}

private static class SingletonHolder {

private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}

2.Double-check idiom with volatile
Java SE 5後新的memory model讓volatile此關鍵字確保所有thread所取得的欄位值是最新被寫入的

private volatile Helper helper = null;

public Helper getHelper() {
if (helper == null) {
sychonized(this)
{
if (helper == null) {
helper = new Helper();
}
}
}
}