2012年12月28日金曜日

GAE/JのスタートガイドをJPA対応する。

GAE/JのスタートガイドをみたところJDOベースになっていたためJPAに対応してみた。

EMF.java
package guestbook;

import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class EMF {
 
 private static final EntityManagerFactory emfInstance =
   Persistence.createEntityManagerFactory("transactions-optional");
 
 private EMF(){}
 
 public static EntityManagerFactory get(){
  return emfInstance;
 }

}
Greeting.java
package guestbook;

import java.util.Date;

import javax.jdo.annotations.Persistent;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.users.User;

@Entity
public class Greeting {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Key key;
 
 private User author;
 
 private String content;
 
 private Date date;
 
    public Greeting(User author, String content, Date date) {
        this.author = author;
        this.content = content;
        this.date = date;
    }

    public Key getKey() {
        return key;
    }

    public User getAuthor() {
        return author;
    }

    public String getContent() {
        return content;
    }

    public Date getDate() {
        return date;
    }

    public void setAuthor(User author) {
        this.author = author;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setDate(Date date) {
        this.date = date;
    } 
 
}

SignServlet.java
package guestbook;

import java.io.IOException;
import java.util.Date;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

public class SignServlet extends HttpServlet{

 private static final Logger log = Logger.getLogger(SignServlet.class.getName());
 
 public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException{
  UserService userService = UserServiceFactory.getUserService();
  User user = userService.getCurrentUser();
  String content = req.getParameter("content");
  Date date = new Date();
  Greeting greeting = new Greeting(user,content,date);
  EntityManager em = EMF.get().createEntityManager();
  try{
   em.persist(greeting);
  }finally{
   em.close();
  }
  resp.sendRedirect("/test.jsp");
 }
 
}
test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.List" %>
<%@ page import="javax.persistence.EntityManager" %> 
<%@ page import="com.google.appengine.api.users.User" %>
<%@ page import="com.google.appengine.api.users.UserService" %>
<%@ page import="com.google.appengine.api.users.UserServiceFactory" %>
<%@ page import="guestbook.Greeting" %>
<%@ page import="guestbook.EMF" %>

<html>
  <body>
   <head>
    <link type="text/css" rel="stylesheet" href="/stylesheet/main.css" />
   </head>
<%
    UserService userService = UserServiceFactory.getUserService();
    User user = userService.getCurrentUser();
    if (user != null) {
%>
<p>Hello, <%= user.getNickname() %>! (You can
<a href="<%= userService.createLogoutURL(request.getRequestURI()) %>">sign out</a>.)</p>
<%
    } else {
%>
<p>Hello!!
<a href="<%= userService.createLoginURL(request.getRequestURI()) %>">Sign in</a>
to include your name with greetings you post.</p>
<%
    }
%>
<%
 EntityManager em = EMF.get().createEntityManager();
 String query = "select i from Greeting i";
 List<Greeting> greetings = (List<Greeting>)em.createQuery(query).getResultList();
 if(greetings.isEmpty()){
%>
<p>The guestbook has no messages.</p>
<%
 }else{
  
  for(Greeting g: greetings){
   if(g.getAuthor() == null){  
%>
<p>An anonymous person wrote:</p>
<%
   } else {
%>
<p><b><%= g.getAuthor().getNickname() %></b> wrote:</p>
<%
   }
%>
<blockquote><%= g.getContent() %></blockquote>
<%
  }
 }
 em.close();
%>
  <form action="/sign" method="post">
    <div><textarea name="content" rows="3" cols="60"></textarea></div>
    <div><input type="submit" value="Post Greeting" /></div>
  </form>
  </body>
</html>

2012年9月16日日曜日

ピアノの楽譜をアルトサックスの楽譜に変える

ピアノの楽譜をアルトサックスで吹こうとするとアルトサックスの「ド」がピアノでいうと「ミb」になってしまうのでピアノとあわせようとすると音が合わないことになる。 これはアルトサックスはEbをド、ピアノはCをドとして楽譜が記載されるからになる。





















上の5度圏でいうとアルトサックスはEbの調でピアノはCの調で楽譜が書かれる。 だからピアノの調で書かれた楽譜をアルトサックスで吹くには5度圏でいうと右に3つずらせばいい(らしい)。 たとえばCの調で書かれていたらAの調にすればいい(らしい)。 この調を右に3つずらす方法としては人手でやる方法もあるがソフトを使ったほうが簡単だ。 転調は無料で公開されているFinale Nodepad 2012を使うとすぐにできる。 やり方の例は以下になる。

 1)ピアノ用に楽譜を書く。ここでは調をCメジャーで書いている。









2)調合ツールのボタンを押す。







3)3つ上の調を選択してOKボタンを押す。ここではAメジャーを選択。














4)アルトサックス用の楽譜ができる。








試したらできたぐらいのことを記事にしただけなのでもし間違えていたらコメントで指摘ください。

2012年9月5日水曜日

Threadの呼ぶ順番を制御してみる

Threadの呼ぶ順番を制御するには単純にrunメソッドの最後に呼びたいスレッドを呼び出せばよいだけであった。複数のスレッドの終了を前提として起動する場合は前提となるスレッドの終了時にカウントして待ち合わせを行うスレッドの数に達したら起動すればよい。notifyメソッドは起こしたいスレッドを指定できないのでスレッド関係の処理は順序の制御が難しそうだと思われがちだが結構単純にできた。
public class ThreadTest {

 static Thread1 t1 = new Thread1();
 static Thread2 t2 = new Thread2();
 static Thread3 t3 = new Thread3();
 static Thread4 t4 = new Thread4();

 public static void main(String[] args) {

  t1.start();
  t2.start();
 }

 static class Thread1 extends Thread {

  public void run() {
   System.out.println("t1");
   t3.fire();
   t4.fire();
  }
 }

 static class Thread2 extends Thread {

  public void run() {
   System.out.println("t2");
   t3.fire();
   t4.fire();
  }
 }

 static class Thread3 extends Thread {
  int i = 0;

  public void fire() {
   if (++i >= 2) {
    start();
   }
  }

  public void run() {
   System.out.println("t3");
  }

 }

 static class Thread4 extends Thread {
  int i = 0;

  public void fire() {
   if (++i >= 2) {
    start();
   }
  }

  public void run() {
   System.out.println("t4");
  }

 }

}

2012年6月5日火曜日

GAEのローカル実行時にJettyのプロセスを終了させて確実に起動させる方法

Google Apps EngineをAntで実行したのですがマニュアル通りにやってもJettyのjava.exeのプロセスが残ったままだったので利用しているポート番号からJettyのプロセスを終了させてからJettyを起動するようにするとうまくいきました。

 build.xmlのrunserverタスク部分
<target depends="datanucleusenhance" description="Starts the development server." name="runserver">
  <exec executable="kill-jetty.bat">
    <dev_appserver port="8888" war="war">
    </dev_appserver>
  </exec>
</target>
kill-jetty.bat
FOR /F "tokens=5 delims= " %P IN ('netstat -a -n -o ^| findstr :8888') DO TaskKill.exe /F /PID %P
他にもっと簡単な方法があるのか分からないがこういうノウハウがあまりないのはなんでだろうか?というかTOMCATだとデプロイするだけで自動的にアプリケーションをロードしてくれるからこんなことは考えなくてもよかったりする。

参考
 Google Apps Engine - Apache Ant の使用
 GAE/J の開発で ant を使うと java.exe プロセスが残る [NT]
 Kill a Process by Looking up the Port being used by it from a .BAT

追記(2013/1/27)

macでも試したところ同じようにjettyのプロセスが残っていたので起動時に一旦プロセスを削除する処理を書いてみました。ポート番号からプロセスをkillする処理が割と簡単に書けました。

<target name="runserver" depends="compile"
    description="Starts the development server.">
   <exec executable="/bin/bash">
      <arg value="kill-jetty.sh"/>
   </exec> 
   <dev_appserver war="war" port="8888"/>
</target>
kill-jetty.sh
kill -9 `lsof -a -t -i:8888 -c java`

2012年5月30日水曜日

JSON in Javaのサンプル

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class JSONTest {

 public static void main(String[] args) {
  JSONObject chat = new JSONObject();
  JSONArray messages = new JSONArray();
  JSONObject message = new JSONObject();
  try {
   chat.put("username", "fc");
   chat.put("chat", messages);
   messages.put(message);
   message.put("username", "user1");
   message.put("message", "hello");
   System.out.println(chat.toString());
  } catch (JSONException e) {
   e.printStackTrace();
  }

 }

}
JSONライブラリには色々ありますがJSON公式のorg.json.*パッケージをまずは使いますよね? ライブラリはJSON in Javaから入手できます。 このうちJSONObjectとJSONArrayを使ったサンプルプログラムを作ってみました。 これを動かすと以下のようなJSONが出力されます。 たぶん複雑になると直に書くより楽になるはず。
{"username":"fc","chat":[{"message":"hello","username":"user1"}]}

setIntervalとclearIntervalのサンプル

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
<title>Count Test</title>
</head>
<body>
 <script language="JavaScript">
  var id = setInterval("count()", 300);
  var i = 0;
  function count() {
   var counter = document.getElementById("counter");
   counter.value = i;
   i++;

  }
  function stop() {
   clearInterval(id);
  }
 </script>
 <input type="text" id="counter"></input>
 <button type="button" onclick="stop()">stop</button>
</body>
</html>
ただカウントしていってボタンを押すとストップするだけです。 Count Test

2012年5月19日土曜日

HelloWorld(Socket編)

Socketを使ったHelloWorldです。
クライアントがサーバにアクセスするとhelloという文字列が返却されます。

ServerTest.java
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest {
 public static void main(String[] args) {
  int port = 5000;
  try {
   ServerSocket serverSocket = new ServerSocket(port);
   while (true) {
    Socket socket = serverSocket.accept();
    OutputStream os = socket.getOutputStream();
    DataOutputStream dos = new DataOutputStream(os);
    dos.writeBytes("hello");
    socket.close();
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}
ClientTest.java
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

public class ClientTest {
  public static void main(String[] args) {
  String host = "localhost";
  int port = 5000;
  Socket socket = new Socket();
  try {
   socket.connect(new InetSocketAddress(host, port));
   InputStream is = socket.getInputStream();
   DataInputStream dis = new DataInputStream(is);
   byte[] buffer = new byte[1024];
   StringBuffer sb = new StringBuffer();
   int length = 0;
   while ((length = dis.read(buffer)) != -1) {
    sb.append(new String(buffer, 0, length));
    System.out.println(sb.toString());
   }
   socket.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}

2012年5月14日月曜日

Cookieの参照方法(Chrome編)


ChromeでCookieの参照方法を調べたところ3つあったのでメモします。

1)JavaScript documentオブジェクトを参照する。
 
 ①アドレス欄にjavascript:document.cookie;と入力する。

 こちらはどのブラウザでも確認できると思います。

2)開発ツールを利用する。

 ①右クリック後に要素を検証を選択。
 ②Developer Toolsダイアログの表示後にResourcesタブを選択。
 ③Cookiesの要素を選択するとCookieの内容を確認できる。

3)設定画面から確認する。

 ①設定画面を開く。
 ②高度な設定を選択する。
 ③コンテンツの設定を選択。
 ④すべてのCookieとサイトデータを選択。

 これを確認するとすべてのCookieとサイトデータ(ローカルストレージなど)が確認できます。

 動作をみるとタブごとにCookieの情報は保持していて新しいタブを開いて新規のURLにアクセスする
 とすべてのCookieとサイトデータからアクセスしようとしているURLに対応しているCookieを
 取り出して新しいタブから他のタブですでにログインしているサイトにアクセスしている場合も
 ログイン状態などを確保しているようだ。

 Cookieの実際のデータはSQLiteを利用しているのでそれを直接見る方法も考えられるが
 少しめんどくさそうなのでやめておく。。

2012年3月13日火曜日

JavaPathFinderのインストール方法(コマンドライン編)

Debian LinuxにJavaPathFinderをコマンドラインで動くようにインストールしたのでメモします。

1) /etc/apt/source.listを修正

   SunのJDKをインストールするため/etc/apt/source.listの以下記載を修正

[修正前]deb http://ftp.jp.debian.org/debian/ squeeze main
[修正後]deb http://ftp.jp.debian.org/debian/ squeeze main non-free

2)リポジトリを更新

> apt-get update 

3)JDK6をインストール

> apt-get install sun-java6-jdk

4)利用するJavaを変更する

以下コマンドよりインストールしたSunのJavaを選択する。
> update-alternatives --config java 

選択するJavaのパスは以下。
/usr/lib/jvm/java-6-sun/jre/bin/java 

JavaPathFinderのビルドはSunのJavaに

5)Antをインストール

apt-get install ant

6)Mercurialをインストール

> apt-get install mercurial

7)JPFをクローン

> hg clone http://babelfish.arc.nasa.gov/hg/jpf/jpf-core

8)ビルド

クローンしたjpf-coreフォルダに移動してantコマンドを実行

9)サンプルを動作確認

> bin/jpf HelloWorld

以下のように表示されたらインストール完了

JavaPathfinder v6.0 (rev 679) - (C) RIACS/NASA Ames Research Center


====================================================== system under test
application: HelloWorld.java

====================================================== search started: 12/03/13 22:27
I won't say it!

====================================================== results
no errors detected

====================================================== statistics
elapsed time:       00:00:00
states:             new=1, visited=0, backtracked=1, end=1
search:             maxDepth=1, constraints hit=0
choice generators:  thread=1 (signal=0, lock=1, shared ref=0), data=0
heap:               new=319, released=11, max live=319, gc-cycles=1
instructions:       2902
max memory:         15MB
loaded code:        classes=74, methods=956

====================================================== search finished: 12/03/13 22:27

10)任意のクラスを検証する場合

> <jpf-core-dir>/bin/jpf +classpath=. <application-main-class>



2012年2月20日月曜日

2012年2月16日木曜日

レジ

レジでものすごい量の商品を買う人の後ろで待っているとすごく時間がかかってしまった。こんな時はRFIDを利用したレジがあればすぐに清算が終わるのになあと思ってしまった。けれどキウイを数えたりする場合など生ものの場合は扱うのが難しそうだ。またRFIDのレジが普及してもレジの人がいなくなるのはさびしい気がした。それにしてもRFIDのレジは結構昔からできているはずだけどなんで普及しないのだろう。

2012年2月15日水曜日

白鳥

この前、白鳥は一見優雅に泳いでいるように見えるが水面下では必死に足を動かしているという話を聞いた。ものすごく順調にいってそうな会社や人も実はものすごい必死でがんばっているのだそうです。そう考えるとなかなか不思議な構図ではありますね。