BlazeDSのCore/Commonだけでさくっと通信する。
世の中若干のBlazeDSブームですが、それにのっかって1ネタ紹介。
(ちょい追記)
BlazeDSのRemotingを使わず、AMF通信のライブラリとしてCore/Commonだけを使って通信する方法です。
それなりに簡単。
BlazeDSは実はCoreとCommonは依存関係がそんなにありません。
backport-util-concurrentとか、xalanとかなくても動く。
というわけで、その2つだけで実は楽に通信できます。
以下サンプル。エラー処理とかちょっと適当だけど^^;
肝は上のエントリでも書きましたが、1回目のリクエストは単なるPINGでそれに
きちんとResponseしてやることと、実データのResponseにヘッダーできちんとバージョンを埋め込むところかな。
RemotingMessageで送られてくるdestinationやoperationに規約をあたえてあげれば
いろいろごにょごにょできますよ、と。わずらわしい設定ファイルも全然いらないのです。
(追記)
あ。言い忘れたけど、これはRemotingだけです。
pushとかできないし、HTTP Proxyとかもないです。
でも擬似pushどれだけ使うのかは若干の疑問だなあー^^;
package amftest.filter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import amftest2.Person; import flex.messaging.MessageException; import flex.messaging.io.MessageDeserializer; import flex.messaging.io.MessageIOConstants; import flex.messaging.io.MessageSerializer; import flex.messaging.io.SerializationContext; import flex.messaging.io.TypeMarshallingContext; 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.AmfTrace; import flex.messaging.io.amf.MessageBody; import flex.messaging.messages.AcknowledgeMessage; import flex.messaging.messages.CommandMessage; import flex.messaging.messages.ErrorMessage; import flex.messaging.messages.Message; import flex.messaging.messages.RemotingMessage; public class AMFFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { TypeMarshallingContext .setTypeMarshallingContext(new TypeMarshallingContext() { @Override public void setClassLoader(ClassLoader loader) { super.setClassLoader(Thread.currentThread() .getContextClassLoader()); } }); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { final ActionContext actionContext = new ActionContext(); final HttpServletRequest req = (HttpServletRequest) request; final HttpServletResponse res = (HttpServletResponse) response; String contentType = req.getHeader("content-type"); String flashVer = req.getHeader("x-flash-version"); if (contentType.equals("application/x-amf") && (flashVer == null || "".equals(flashVer))) { chain.doFilter(req, res); return; } try { processRequestMessage(req, actionContext); createResponseMessage(actionContext); processOutputMessage(res, actionContext); } catch (Throwable t) { t.printStackTrace(); String errorStr = t.getMessage(); if (errorStr == null) errorStr = t.getClass().getName(); MessageException e = new MessageException(); e.setMessage(10000, new Object[] { errorStr }); Object data = actionContext.getRequestMessageBody().getData(); Message inMessage = null; if (data instanceof List) { inMessage = (Message) ((List<?>) data).get(0); } else if (data.getClass().isArray()) { inMessage = (Message) Array.get(data, 0); } final ErrorMessage errorMessage = createErrorMessage(e, inMessage); actionContext.setStatus(MessageIOConstants.STATUS_ERR); final MessageBody responseMessageBody = actionContext .getResponseMessageBody(); responseMessageBody .setReplyMethod(MessageIOConstants.STATUS_METHOD); responseMessageBody.setData(errorMessage); } } protected ErrorMessage createErrorMessage(MessageException lme, Message inMessage) { ErrorMessage outMessage = new ErrorMessage(); lme.createErrorMessage(); outMessage.setCorrelationId(inMessage.getMessageId()); outMessage.setDestination(inMessage.getDestination()); outMessage.setClientId(inMessage.getClientId()); return outMessage; } protected void processRequestMessage(HttpServletRequest req, ActionContext actionContext) throws Exception { SerializationContext serializationContext = SerializationContext .getSerializationContext(); MessageDeserializer deserializer = new AmfMessageDeserializer(); InputStream inputStream = req.getInputStream(); deserializer.initialize(serializationContext, inputStream, new AmfTrace()); int contentLength = req.getContentLength(); actionContext.setDeserializedBytes(contentLength); actionContext.setRequestMessage(new ActionMessage()); deserializer.readMessage(actionContext.getRequestMessage(), actionContext); } protected void createResponseMessage(ActionContext actionContext) throws Exception { MessageBody requestBody = actionContext.getRequestMessageBody(); MessageBody responseBody = new MessageBody(); responseBody.setTargetURI(requestBody.getResponseURI()); Object bodyCandidate = requestBody.getData(); if (bodyCandidate.getClass().isArray()) { Object[] bodyObjects = (Object[]) bodyCandidate; for (int i = 0; i < bodyObjects.length; i++) { Object body = bodyObjects[i]; handleBody(responseBody, body); } } else { handleBody(responseBody, bodyCandidate); } ActionMessage responseMessage = new ActionMessage(); responseMessage.setVersion(actionContext.getVersion()); responseMessage.addBody(responseBody); actionContext.setResponseMessage(responseMessage); } protected void handleBody(MessageBody responseBody, Object body) { if (body instanceof CommandMessage) { CommandMessage command = (CommandMessage) body; if (command.getOperation() == CommandMessage.CLIENT_PING_OPERATION) { responseBody.setReplyMethod(MessageIOConstants.RESULT_METHOD); } } else if (body instanceof RemotingMessage) { RemotingMessage remoting = (RemotingMessage) body; System.out.println("destination:" + remoting.getDestination()); System.out.println("operation:" + remoting.getOperation()); Person person = (Person) remoting.getParameters().get(0); System.out.println("Person:name=" + person.getStr()); responseBody.setReplyMethod(MessageIOConstants.RESULT_METHOD); AcknowledgeMessage resultMessage = new AcknowledgeMessage(); resultMessage.setClientId(remoting.getClientId()); resultMessage.setCorrelationId(remoting.getMessageId()); resultMessage.setDestination(remoting.getDestination()); Person p = new Person(); p.setStr("100年後の" + person.getNum()); p.setNum(person.getNum() + 100); Person p2 = new Person(); p2.setStr("101年後の" + person.getNum()); p2.setNum(person.getNum() + 101); List<Person> list = new ArrayList<Person>(); list.add(p); list.add(p2); resultMessage.setBody(list); resultMessage.setHeader(CommandMessage.MESSAGING_VERSION, new Double(3)); responseBody.setData(resultMessage); } } protected void processOutputMessage(HttpServletResponse res, ActionContext actionContext) throws Exception { SerializationContext dsContext = SerializationContext .getSerializationContext(); MessageSerializer serializer = new AmfMessageSerializer(); OutputStream outputStream = res.getOutputStream(); serializer.initialize(dsContext, outputStream, new AmfTrace()); serializer.writeMessage(actionContext.getResponseMessage()); } public void destroy() { } }