You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mina.apache.org by angel figueroa <an...@updatecom.com> on 2007/05/14 02:58:05 UTC

ByteArrayProtocolCodecFactory Fail on Client Decoder

I am implementing a ProtocolCodecFilter for binay data.
 My protocol format is Message Length (2 bytes)  + data (n-byes) + End
Delimiter (Hex 03)

 When i use from the server for received data from Client not Problem. It
received and send without any problem. Always i use byte array.

But from the client i can send to the server without any problem.  But when
the client received the data using the same decoder. it generate the
following error, including the correct data send by the server

Execption [java.lang.UnsupportedOperationException (Hexdump: 00 46 49 53 4F
30 3
0 36 30 30 30 30 34 34 30 38 31 30 38 32 32 30 30 30 30 30 30 32 30 30 30 30
30
30 30 34 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 35 31 33 32 30 35 35
34 34
 30 30 30 30 30 39 30 30 30 30 31 03)]

The instruction that generate the error was byte [] Data = (byte[])
in.array();

Why the client generate this error using the same decoder.

Include the 
1. ByteArrayProtocolCodecFactory
2. ByteArrayProtocolEncoder 
3. ByteArrayProtocolDecoder 

Thanks for all the help.
Regards
Angel Figueroa


--------------------------------------------------------------------------------------------------------------------
1. ByteArrayProtocolCodecFactory

package CustomProtocolCodeFilter;

import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.ProtocolDecoder;

/**
 *
 * @author ??????????????
 */
public class ByteArrayProtocolCodecFactory implements  ProtocolCodecFactory
{
    
    /** Creates a new instance of ByteArrayProtocolCodecFactory */
    public ByteArrayProtocolCodecFactory() 
    {
    }
    
    public ProtocolDecoder getDecoder() throws Exception 
    {
        return new  ByteArrayProtocolDecoder ();
    }
    
    public ProtocolEncoder getEncoder() throws Exception 
    {
        return new ByteArrayProtocolEncoder();
    }
    
}
-----------------------------------------------------------------------------------------------------------
2. ByteArrayProtocolEncoder 

package CustomProtocolCodeFilter;

import java.util.UUID;
import org.apache.commons.lang.StringUtils;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;

/**
 *
 * @author ????????
 */
public class ByteArrayProtocolEncoder extends ProtocolEncoderAdapter
{
    
    /** Creates a new instance of ByteArrayProtocolEncoder */
    public ByteArrayProtocolEncoder() 
    {
    }
    
    public void encode( IoSession session, Object message,
ProtocolEncoderOutput out ) throws Exception 
    {
                
       
//----------------------------------------------------------------------
        // Data Send from the Application
       
//----------------------------------------------------------------------
        byte[] DatabBytes = (byte[]) message;
        
       
//----------------------------------------------------------------------
        // Allocate the buffer large enogth to hold the protocol
        // 
        // protocol
        // 2B Message Length + Data + 1B Delimiter
       
//----------------------------------------------------------------------    
        ByteBuffer buffer = ByteBuffer.allocate(DatabBytes.length + 3);
        
       
//----------------------------------------------------------------------
        // write the Header - 2 bytes
       
//----------------------------------------------------------------------
        buffer.putShort((short)(DatabBytes.length + 1));
        
       
//----------------------------------------------------------------------
        // write the payload - data n byte maximo 2048
       
//----------------------------------------------------------------------
        buffer.put(DatabBytes);
        
       
//----------------------------------------------------------------------
        // write the delimiter - end delimiter
       
//----------------------------------------------------------------------
        buffer.put((byte) 3);
        
       
//----------------------------------------------------------------------
        // write the protocol out
       
//----------------------------------------------------------------------    
        buffer.flip();
        out.write(buffer);         
                
    }        
}

---------------------------------------------------------------------------------------------------
3. ByteArrayProtocolDecoder 

package CustomProtocolCodeFilter;

import java.util.UUID;
import org.apache.commons.lang.StringUtils;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;


/**
 *
 * @author UpdateCom
 */
public class ByteArrayProtocolDecoder extends CumulativeProtocolDecoder 
{
    
    /** Creates a new instance of ByteArrayProtocolDecoder */
    public ByteArrayProtocolDecoder() 
    {
        DECODER_STATE_KEY = createId() + ".DECODER_STATE";
    }

   
//--------------------------------------------------------------------------
    // Decoder State Key
   
//--------------------------------------------------------------------------
    private String DECODER_STATE_KEY =
"";//ByteArrayProtocolDecoder.class.getName() + ".DECODER_STATE";
    
   
//--------------------------------------------------------------------------
    // method for creatinf a unique id
   
//--------------------------------------------------------------------------
    private String createId() 
    {
        UUID uuid = java.util.UUID.randomUUID();                  
        return
StringUtils.upperCase(StringUtils.remove(uuid.toString(),"-"));
    }
    
   
//--------------------------------------------------------------------------
    // Class to maintain the state of the decoder
   
//--------------------------------------------------------------------------
    private class DecoderState 
    {                        
       
//----------------------------------------------------------------------
        // whether we have already read the fixed-length header
       
//----------------------------------------------------------------------
        boolean headerRead = false;
        
       
//----------------------------------------------------------------------
        // the length of the payload 
       
//----------------------------------------------------------------------
        int length;
    }     
    
   
//--------------------------------------------------------------------------
    // the header has a fixed length of 2 bytes  
   
//--------------------------------------------------------------------------
    private final static int HEADER_LENGTH = 2;
            
   
//--------------------------------------------------------------------------
    // Decode Routine
   
//--------------------------------------------------------------------------
    protected boolean doDecode(IoSession session, ByteBuffer in,
ProtocolDecoderOutput out) throws Exception 
    {                                       
          System.out.printf ("Enter the doDecode \n");
          
          if ( in instanceof ByteBuffer)
          {
              System.out.printf (" ByteBuffer - yes \n");              
          }
          else
          {
              System.out.printf (" ByteBuffer - No \n");                            
          }
                              
         
//--------------------------------------------------------------------
          // Get the state from the Session an Attribute of
DECODER_STATE_KEY
         
//--------------------------------------------------------------------
          DecoderState state = (DecoderState) session.getAttribute
(DECODER_STATE_KEY);
          
          System.out.printf ("Session ID [%s] \n" ,DECODER_STATE_KEY);
          System.out.printf ("Data [%s]        \n",in.getHexDump());         
          System.out.printf ("Next Line is Fail When using on client. Server
Pass without any problem\n");
          byte [] Data = (byte[]) in.array();          
          System.out.printf ("Length     [%d]  \n",Data.length);
                    
         
//--------------------------------------------------------------------
          // verify the state 
         
//--------------------------------------------------------------------
          if (state == null) 
          {
              state = new DecoderState();
              session.setAttribute(DECODER_STATE_KEY, state);
          }
          
         
//--------------------------------------------------------------------
          // verify the state = not enogth data received
         
//--------------------------------------------------------------------
          if (!state.headerRead) 
          {
                // we have not yet read the header => check if have enough
bytes to read the fixed-length header
                if (in.remaining() >= HEADER_LENGTH) 
                {
                    state.length     = in.getShort();
                    state.headerRead = true;
                    
                    System.out.printf ("Remain [%d] Header Lenth [%d]
State.length [%d] \n",in.remaining(),HEADER_LENGTH,state.length);
                } 
                else 
                {
                    // not enough bytes to decode a message, MINA will call
us again when there is more data available
                    return false;
                }
          }
          
         
//--------------------------------------------------------------------
          // enogth data received for processing
         
//--------------------------------------------------------------------
          if (state.headerRead) 
          {
                // we have already read the lengt header, check if all the
data is available
              
                if (in.remaining() >= state.length) 
                {                                        
                   
//----------------------------------------------------------
                    // ok, message complete
                   
//----------------------------------------------------------
                    byte[] DataBytes = new byte[state.length-1];
                    
                   
//----------------------------------------------------------
                    // extract the data from the byte buffer to the byte
array
                   
//----------------------------------------------------------
                   
System.arraycopy(in.array(),2,DataBytes,0,state.length-1);
                                                            
                   
//----------------------------------------------------------
                    // this will cause IoHandler.messageReceived() to be
called with a byte[] as the message
                   
//----------------------------------------------------------
                    out.write(DataBytes);
                    
                   
//----------------------------------------------------------
                    // remove the decoder state to be ready for the next
message
                   
//----------------------------------------------------------
                    session.removeAttribute(DECODER_STATE_KEY);
                    in.clear();
                    in.compact();
                                        
                    return true;
                }
                // not enough bytes available
                return false;
          }
          return false;
  }             
}


-- 
View this message in context: http://www.nabble.com/ByteArrayProtocolCodecFactory-Fail-on-Client-Decoder-tf3740273.html#a10498894
Sent from the mina dev mailing list archive at Nabble.com.


Re: ByteArrayProtocolCodecFactory Fail on Client Decoder

Posted by Trustin Lee <tr...@gmail.com>.
Hi Angel,

It seems like you allocated a direct buffer.  Please try to allocate a
heap buffer instead of a direct buffer.  You can specify your
preferred buffer type with a boolean parameter.

HTH,
Trustin

On 5/14/07, angel figueroa <an...@updatecom.com> wrote:
>
> I am implementing a ProtocolCodecFilter for binay data.
>  My protocol format is Message Length (2 bytes)  + data (n-byes) + End
> Delimiter (Hex 03)
>
>  When i use from the server for received data from Client not Problem. It
> received and send without any problem. Always i use byte array.
>
> But from the client i can send to the server without any problem.  But when
> the client received the data using the same decoder. it generate the
> following error, including the correct data send by the server
>
> Execption [java.lang.UnsupportedOperationException (Hexdump: 00 46 49 53 4F
> 30 3
> 0 36 30 30 30 30 34 34 30 38 31 30 38 32 32 30 30 30 30 30 30 32 30 30 30 30
> 30
> 30 30 34 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 35 31 33 32 30 35 35
> 34 34
>  30 30 30 30 30 39 30 30 30 30 31 03)]
>
> The instruction that generate the error was byte [] Data = (byte[])
> in.array();
>
> Why the client generate this error using the same decoder.
>
> Include the
> 1. ByteArrayProtocolCodecFactory
> 2. ByteArrayProtocolEncoder
> 3. ByteArrayProtocolDecoder
>
> Thanks for all the help.
> Regards
> Angel Figueroa
>
>
> --------------------------------------------------------------------------------------------------------------------
> 1. ByteArrayProtocolCodecFactory
>
> package CustomProtocolCodeFilter;
>
> import org.apache.mina.filter.codec.ProtocolCodecFactory;
> import org.apache.mina.filter.codec.ProtocolEncoder;
> import org.apache.mina.filter.codec.ProtocolDecoder;
>
> /**
>  *
>  * @author ??????????????
>  */
> public class ByteArrayProtocolCodecFactory implements  ProtocolCodecFactory
> {
>
>     /** Creates a new instance of ByteArrayProtocolCodecFactory */
>     public ByteArrayProtocolCodecFactory()
>     {
>     }
>
>     public ProtocolDecoder getDecoder() throws Exception
>     {
>         return new  ByteArrayProtocolDecoder ();
>     }
>
>     public ProtocolEncoder getEncoder() throws Exception
>     {
>         return new ByteArrayProtocolEncoder();
>     }
>
> }
> -----------------------------------------------------------------------------------------------------------
> 2. ByteArrayProtocolEncoder
>
> package CustomProtocolCodeFilter;
>
> import java.util.UUID;
> import org.apache.commons.lang.StringUtils;
> import org.apache.mina.common.ByteBuffer;
> import org.apache.mina.common.IoSession;
> import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
> import org.apache.mina.filter.codec.ProtocolCodecFactory;
> import org.apache.mina.filter.codec.ProtocolDecoder;
> import org.apache.mina.filter.codec.ProtocolDecoderOutput;
> import org.apache.mina.filter.codec.ProtocolEncoder;
> import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
> import org.apache.mina.filter.codec.ProtocolEncoderOutput;
>
> /**
>  *
>  * @author ????????
>  */
> public class ByteArrayProtocolEncoder extends ProtocolEncoderAdapter
> {
>
>     /** Creates a new instance of ByteArrayProtocolEncoder */
>     public ByteArrayProtocolEncoder()
>     {
>     }
>
>     public void encode( IoSession session, Object message,
> ProtocolEncoderOutput out ) throws Exception
>     {
>
>
> //----------------------------------------------------------------------
>         // Data Send from the Application
>
> //----------------------------------------------------------------------
>         byte[] DatabBytes = (byte[]) message;
>
>
> //----------------------------------------------------------------------
>         // Allocate the buffer large enogth to hold the protocol
>         //
>         // protocol
>         // 2B Message Length + Data + 1B Delimiter
>
> //----------------------------------------------------------------------
>         ByteBuffer buffer = ByteBuffer.allocate(DatabBytes.length + 3);
>
>
> //----------------------------------------------------------------------
>         // write the Header - 2 bytes
>
> //----------------------------------------------------------------------
>         buffer.putShort((short)(DatabBytes.length + 1));
>
>
> //----------------------------------------------------------------------
>         // write the payload - data n byte maximo 2048
>
> //----------------------------------------------------------------------
>         buffer.put(DatabBytes);
>
>
> //----------------------------------------------------------------------
>         // write the delimiter - end delimiter
>
> //----------------------------------------------------------------------
>         buffer.put((byte) 3);
>
>
> //----------------------------------------------------------------------
>         // write the protocol out
>
> //----------------------------------------------------------------------
>         buffer.flip();
>         out.write(buffer);
>
>     }
> }
>
> ---------------------------------------------------------------------------------------------------
> 3. ByteArrayProtocolDecoder
>
> package CustomProtocolCodeFilter;
>
> import java.util.UUID;
> import org.apache.commons.lang.StringUtils;
> import org.apache.mina.common.ByteBuffer;
> import org.apache.mina.common.IoSession;
> import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
> import org.apache.mina.filter.codec.ProtocolCodecFactory;
> import org.apache.mina.filter.codec.ProtocolDecoder;
> import org.apache.mina.filter.codec.ProtocolDecoderOutput;
> import org.apache.mina.filter.codec.ProtocolEncoder;
> import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
> import org.apache.mina.filter.codec.ProtocolEncoderOutput;
>
>
> /**
>  *
>  * @author UpdateCom
>  */
> public class ByteArrayProtocolDecoder extends CumulativeProtocolDecoder
> {
>
>     /** Creates a new instance of ByteArrayProtocolDecoder */
>     public ByteArrayProtocolDecoder()
>     {
>         DECODER_STATE_KEY = createId() + ".DECODER_STATE";
>     }
>
>
> //--------------------------------------------------------------------------
>     // Decoder State Key
>
> //--------------------------------------------------------------------------
>     private String DECODER_STATE_KEY =
> "";//ByteArrayProtocolDecoder.class.getName() + ".DECODER_STATE";
>
>
> //--------------------------------------------------------------------------
>     // method for creatinf a unique id
>
> //--------------------------------------------------------------------------
>     private String createId()
>     {
>         UUID uuid = java.util.UUID.randomUUID();
>         return
> StringUtils.upperCase(StringUtils.remove(uuid.toString(),"-"));
>     }
>
>
> //--------------------------------------------------------------------------
>     // Class to maintain the state of the decoder
>
> //--------------------------------------------------------------------------
>     private class DecoderState
>     {
>
> //----------------------------------------------------------------------
>         // whether we have already read the fixed-length header
>
> //----------------------------------------------------------------------
>         boolean headerRead = false;
>
>
> //----------------------------------------------------------------------
>         // the length of the payload
>
> //----------------------------------------------------------------------
>         int length;
>     }
>
>
> //--------------------------------------------------------------------------
>     // the header has a fixed length of 2 bytes
>
> //--------------------------------------------------------------------------
>     private final static int HEADER_LENGTH = 2;
>
>
> //--------------------------------------------------------------------------
>     // Decode Routine
>
> //--------------------------------------------------------------------------
>     protected boolean doDecode(IoSession session, ByteBuffer in,
> ProtocolDecoderOutput out) throws Exception
>     {
>           System.out.printf ("Enter the doDecode \n");
>
>           if ( in instanceof ByteBuffer)
>           {
>               System.out.printf (" ByteBuffer - yes \n");
>           }
>           else
>           {
>               System.out.printf (" ByteBuffer - No \n");
>           }
>
>
> //--------------------------------------------------------------------
>           // Get the state from the Session an Attribute of
> DECODER_STATE_KEY
>
> //--------------------------------------------------------------------
>           DecoderState state = (DecoderState) session.getAttribute
> (DECODER_STATE_KEY);
>
>           System.out.printf ("Session ID [%s] \n" ,DECODER_STATE_KEY);
>           System.out.printf ("Data [%s]        \n",in.getHexDump());
>           System.out.printf ("Next Line is Fail When using on client. Server
> Pass without any problem\n");
>           byte [] Data = (byte[]) in.array();
>           System.out.printf ("Length     [%d]  \n",Data.length);
>
>
> //--------------------------------------------------------------------
>           // verify the state
>
> //--------------------------------------------------------------------
>           if (state == null)
>           {
>               state = new DecoderState();
>               session.setAttribute(DECODER_STATE_KEY, state);
>           }
>
>
> //--------------------------------------------------------------------
>           // verify the state = not enogth data received
>
> //--------------------------------------------------------------------
>           if (!state.headerRead)
>           {
>                 // we have not yet read the header => check if have enough
> bytes to read the fixed-length header
>                 if (in.remaining() >= HEADER_LENGTH)
>                 {
>                     state.length     = in.getShort();
>                     state.headerRead = true;
>
>                     System.out.printf ("Remain [%d] Header Lenth [%d]
> State.length [%d] \n",in.remaining(),HEADER_LENGTH,state.length);
>                 }
>                 else
>                 {
>                     // not enough bytes to decode a message, MINA will call
> us again when there is more data available
>                     return false;
>                 }
>           }
>
>
> //--------------------------------------------------------------------
>           // enogth data received for processing
>
> //--------------------------------------------------------------------
>           if (state.headerRead)
>           {
>                 // we have already read the lengt header, check if all the
> data is available
>
>                 if (in.remaining() >= state.length)
>                 {
>
> //----------------------------------------------------------
>                     // ok, message complete
>
> //----------------------------------------------------------
>                     byte[] DataBytes = new byte[state.length-1];
>
>
> //----------------------------------------------------------
>                     // extract the data from the byte buffer to the byte
> array
>
> //----------------------------------------------------------
>
> System.arraycopy(in.array(),2,DataBytes,0,state.length-1);
>
>
> //----------------------------------------------------------
>                     // this will cause IoHandler.messageReceived() to be
> called with a byte[] as the message
>
> //----------------------------------------------------------
>                     out.write(DataBytes);
>
>
> //----------------------------------------------------------
>                     // remove the decoder state to be ready for the next
> message
>
> //----------------------------------------------------------
>                     session.removeAttribute(DECODER_STATE_KEY);
>                     in.clear();
>                     in.compact();
>
>                     return true;
>                 }
>                 // not enough bytes available
>                 return false;
>           }
>           return false;
>   }
> }
>
>
> --
> View this message in context: http://www.nabble.com/ByteArrayProtocolCodecFactory-Fail-on-Client-Decoder-tf3740273.html#a10498894
> Sent from the mina dev mailing list archive at Nabble.com.
>
>


-- 
what we call human nature is actually human habit
--
http://gleamynode.net/
--
PGP Key ID: 0x0255ECA6