AppletでAMF3通信

BlazeDSからAMF3の通信機能だけを取り出して、懐かしのApplet-Servlet通信AMF3版を作ってみました。
http://hatena.souko105.net/amftest/AMF3Applet.jsp
名前を入れると、サーバ側で名前が加工されて戻ってきます。
以下アプレットのソースです。

package amftest.applet;
import java.awt.Container;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import amftest.Person;
import flex.messaging.io.MessageDeserializer;
import flex.messaging.io.MessageSerializer;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.ActionContext;
import flex.messaging.io.amf.ActionMessage;
import flex.messaging.io.amf.AmfMessageDeserializer;
import flex.messaging.io.amf.AmfMessageSerializer;
import flex.messaging.io.amf.MessageBody;
import flex.messaging.messages.AcknowledgeMessage;
import flex.messaging.messages.RemotingMessage;
import flex.messaging.util.UUIDUtils;

/**
 * 
 * @author c9katayama
 */
public class AMF3Applet extends JApplet {

 private JLabel label;
 private JTextField name;
 private JButton sendButton;
 private JTextArea resultLabel;
 
 private String serverPath;
 
 @Override
 public void init() {
  setSize(300,200);
  serverPath = getParameter("serverPath");
  
  label = new JLabel("お名前は?");
  name = new JTextField();
  sendButton = new JButton("送信");
  resultLabel = new JTextArea();

  sendButton.addMouseListener(new MouseAdapter(){
   public void mouseReleased(MouseEvent arg0) {
    sendAction();
   }
  });
  resultLabel.setEditable(false);
  
  Container container = getContentPane();
  container.setLayout(null);
  
  label.setBounds(0,0,70,20);
  name.setBounds(70,0,70,20);
  sendButton.setBounds(140,0,80,20);
  resultLabel.setBounds(0,30,300,40);
  
  container.add(label);
  container.add(name);
  container.add(sendButton);
  container.add(resultLabel);
 }
 protected void sendAction(){
  OutputStream outputStream = null;
  InputStream inputStream = null;
  try{
   ActionMessage requestMessage = new ActionMessage();
   RemotingMessage remoting = new RemotingMessage();
   MessageBody body = new MessageBody();
   body.setData(new Object[]{remoting});
   requestMessage.addBody(body);
   
   remoting.setClientId(UUIDUtils.createUUID());
   remoting.setDestination("service");
   remoting.setOperation("callMethod");
   
   List paramList = new ArrayList();
   Person person = new Person();
   person.setName(name.getText());
   person.setAge(new Integer(10));
   paramList.add(person);
   
   remoting.setParameters(paramList);    
 
   URL url=new URL(serverPath);
   URLConnection conn = url.openConnection(); 
   conn.setDoOutput(true);
   conn.setDoInput(true);
   conn.setUseCaches(false);
   conn.setRequestProperty("Content-Type","application/x-amf");    
 
   SerializationContext serializationContext = SerializationContext.getSerializationContext();
   MessageSerializer serializer = new AmfMessageSerializer();
   outputStream = conn.getOutputStream();
   serializer.initialize(serializationContext,outputStream,null);
   serializer.writeMessage(requestMessage);
 
   MessageDeserializer deserializer = new AmfMessageDeserializer();
   inputStream = conn.getInputStream();
   deserializer.initialize(serializationContext, inputStream,null);
   ActionMessage responseMessage = new ActionMessage();          
   deserializer.readMessage(responseMessage,new ActionContext());
   
   AcknowledgeMessage ack = (AcknowledgeMessage)responseMessage.getBody(0).getData();
   Person resultPerson = (Person)ack.getBody();
   resultLabel.setText("AMF3 response: name="+resultPerson.getName()+"\nclientID="+ack.getClientId());
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   try{
    inputStream.close();
   }catch(Exception e){    
   }
   try{
    outputStream.close();
   }catch(Exception e){
   }
  }
 } 
}

アプレット側は、

flex.messaging
flex.messaging.config
flex.messaging.io
flex.messaging.io.amf
flex.messaging.io.amf.translator
flex.messaging.io.amf.translator.decoder
flex.messaging.io.amfx
flex.messaging.log
flex.messaging.messages
flex.messaging.util

あたりのクラスを持ってきて、

TypeMarshallingContext#getClassLoaderをThread.currentThread.getContextClassLoaderから取得するように変更
MessageException#getResourceLoader errorMessage周り削除
StatusInfoProxyのserveltExceptionチェック部分
Trace System.getPropertiesからの取得部分をtrycatchに変更

といった部分を変更すると、アプレットで使えるクラス構成に出来ます。
(不要なMessageやログ周りを削れば、もっと削れるとは思います)
変更後のソースは http://hatena.souko105.net/20080328/amf3-src.zip にあります。


AMF3を便利な高速通信ととらえれば、Java to Javaでいろいろ便利に使えるのではないかなと思います。