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();
  }
 }
}