Ahh, long time since I was on pposting end :D

Ok here it goes. The code bellow show mobile application that takes string from user and past it on to servlet. Servlet read it add extra data on front of message and send it back to mobile device that display this new message.

My problem is the red marked part. I'm able to read correct length of sent bytes from server, I'm able to store it in byte array but can not convert back to string.

application system calls will be like this

before transmit name=Peter
length = 23
reading data
Received data = [B@1cb37664
Length 23
str = [B@1cb37664

server calls follows

Print income data: Peter
Response: Received name : 'Peter' length bytes = 23

Any suggestions?

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;

public class GetNpost extends MIDlet implements CommandListener, Runnable
{
    private Display display;
    private Form fmMain;
    private Alert alError;
    private Command cmPOST;
    private Command cmEXIT;
    private TextField tfName;
    private StringItem response;
    private String errorMsg = null;
    //private Thread t;
    private String name;

    private void initialize()
    {
        display = Display.getDisplay(this);

        cmPOST = new Command("POST", Command.SCREEN, 2);
        cmEXIT = new Command("EXIT", Command.EXIT, 1);

        tfName = new TextField("Name:", "", 10, TextField.ANY);

        response = new StringItem("Response: ", "");

        fmMain = new Form("Post Connection");

        fmMain.append(tfName);
        fmMain.append(response);

        fmMain.addCommand(cmEXIT);
        fmMain.addCommand(cmPOST);

        fmMain.setCommandListener(this);
    }

    public void startApp()
    {
        initialize();
        //display = Display.getDisplay(this);
        display.setCurrent(fmMain);
    }

    public void pauseApp() {}

    public void destroyApp(boolean unconditional){}

    public void commandAction(Command c, Displayable s)
    {
        if(c == cmPOST)
        {
            name = tfName.getString();

            try
            {
                Thread t = new Thread(this);
                t.start();
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
        else if(c == cmEXIT)
        {
            destroyApp(false);
            notifyDestroyed();
        }
    }

    public void run()
    {
        HttpConnection http = null;
        OutputStream oStrm = null;
        DataInputStream iStrm = null;
        boolean ret = false;

        String url = "http://localhost:8080/mobile/postServlet.jsp";  // local Tomcat        

        try
        {
            http = (HttpConnection)Connector.open(url);

            http.setRequestMethod(HttpConnection.POST);

            http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            byte data[] = ("name=" + tfName.getString()).getBytes();
            System.out.println("before transmit " + new String(data));
            oStrm = http.openOutputStream();
            oStrm.write(data);
            oStrm.close();
            oStrm = null;

            iStrm = http.openDataInputStream();
            ret = processServerResponce(http, iStrm);
        }
        catch(IOException ioe)
        {
            ioe.printStackTrace();
        }
        finally
        {
            try{
            if(iStrm != null) iStrm.close();
            if(oStrm != null) oStrm.close();
            if(http != null) http.close();
            }
            catch(IOException ioe){}
        }
        if(ret == false)
        {
            showAlert(errorMsg);
        }
    }

    private boolean processServerResponce(HttpConnection http, DataInputStream dStrm) throws IOException
    {
        errorMsg = null;

        if(http.getResponseCode() == HttpConnection.HTTP_OK)
        {
            int length = (int) http.getLength();
            System.out.println("length = " + length);
            String str;
            if(length != -1)
            {
                System.out.println("reading data");
                byte servletData[] = new byte[length];
                //iStrm.read(servletData);
                //DataInputStream dis = http.openDataInputStream();
                dStrm.readFully(servletData);
                System.out.println("Received data = " + servletData + "\nLength " + servletData.length);
                str = servletData.toString();
                System.out.println("str = " + str);
            }
            else
            {
                ByteArrayOutputStream bStrm = new ByteArrayOutputStream();

                int ch;
                while((ch = dStrm.read()) != -1)
                {
                    bStrm.write(ch);
                }
                str = new String(bStrm.toByteArray());
                bStrm.close();
            }

            response.setText(str);
            return true;
        }
        else
        {
            errorMsg = new String(http.getResponseMessage());
            return false;
        }

    }

    private void showAlert(String msg)
    {
        System.out.println(msg);
        alError = new Alert("Error", msg, null, AlertType.ERROR);

        alError.setTimeout(Alert.FOREVER);

        display.setCurrent(alError, fmMain);
    }
}

Servlet

import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;

public class PostServlet extends HttpServlet
{
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		String name = request.getParameter("name");
		System.out.println("Print income data: " + name);
		String message = "Received name : '" + name + "'";
		response.setContentType("text/plain");
		response.setContentLength(message.length());
		System.out.println("Response: " + message + " length bytes = " + message.length() );
		PrintWriter out = response.getWriter();
		out.println(message);
	}
}

Dani AI

Generated

Quick summary and practical fixes (ties to earlier replies by and )

The “[B@1cb37664” output is the JVM printing the byte-array object identity, not the text. The real fixes are: (1) make the servlet send bytes encoded with a known charset, (2) compute Content-Length from the actual bytes, and (3) decode the received bytes on the MIDlet using the same charset. correctly pointed out the byte→text decode; 's note about content types and binary payloads is also relevant.

Server-side checklist (produce exact bytes and length)

  • Encode the text to bytes with a fixed charset (UTF-8 is a good choice).
  • Set the response Content-Type including the charset.
  • Compute Content-Length from the byte array (not from the Java String length).
  • Write raw bytes to the response output stream (so you control exact bytes sent).

Example server-side write (use this pattern so length matches bytes sent):

byte[] outBytes = message.getBytes("UTF-8");
response.setContentType("text/plain; charset=UTF-8");
response.setContentLength(outBytes.length);
ServletOutputStream os = response.getOutputStream();
os.write(outBytes);
os.flush();

Client-side notes for J2ME MIDlet

  • Only use a fixed-size readFully when the reported content-length is correct. If length is unreliable, read until EOF and accumulate bytes.
  • Decode the accumulated bytes with the same charset the servlet declared; do not call toString() on the byte array (that prints the object id).
  • For binary blobs consider sending as multipart or encode the bytes to Base64 and post as text field — easier to parse on older mobile stacks.

Debug tips

  • Log byte counts on both sides (server: outBytes.length, client: receivedBytes.length) and inspect the response headers. Avoid setting Content-Length based on String.length(), since character count != byte count for multibyte encodings.

Recommended Answers

All 10 Replies

Umm, peter, I thought you knew this one. ;-)

str = servletData.toString();

I believe should be

str = new String(servletData);

or

str = new String(servletData, charset);

if the "bytes" are neither ascii, nor UTF, nor the local charset.

The second one (with the toByteArray()) is correct, but if its not working then check out the charset variation.

And Merry Christmas and a Happy New Year! (and if you're not Catholic/Christian/Other Derivatives don't take offense). ;-)

commented: Great mind +7

Hehe, I can't know everything, still in process of learning also I did not have lot of byte array processing till now when I started mobile computing.
Thanx for help, charset encoding was the key :*

If all you want to send is character data, why convert it to a byte stream unless what you posted was just a dummy example.

Some things you should know:

  • application/x-www-form-urlencoded is the default content type used to encode the form data, you don't need to explicitly set it. Similarly, the default content type of an HTTP servlet is text/html.
  • application/x-www-form-urlencoded is the wrong content type if you are sending bytes, you should use multipart/form-data to indicate that your request body contains binary data. (The term request body is relevant only when you are 'POST'ing your data)
  • For sending character only data you should consider constructing a query string having your data in the name-value format and posting it. Here is a small example:
public class ServletApp {
    public static void main(String args[]) {
        try {
            URL url = new URL("http://localhost:8080/mobile/postServlet.jsp");
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod("POST");
            String queryString = "name=sos";
            Writer out = new PrintWriter(conn.getOutputStream());
            out.write(queryString);
            out.close();
            Scanner in = new Scanner(conn.getInputStream());
            System.out.println("Data received--->");
            while(in.hasNext()) {
                System.out.print(in.next() + " ");
            }
            in.close();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}

The problem is I'm little limited on methods available to J2ME, the large code is example from IBM that is widely used with some of my additions for quick learning purpose befor I dive into my coursework.
But I will look more on content type also dig around litle for use of base64 and bouncing castle

Just side notes on some testing done http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); has to be set or servlet will receive null from midlet
Seting up multipart/form-data on servlet side resolve problem with providing charset on midlet side to read byte array. This may be trivial to somebody but all new things to me ;)

Peter,

I am trying to send some text and byte[] messages from a j2me application to a servlet. I am able to get all text messages but unable to get byte[] message correctly. I set http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded") in client side and response.setContentType("multipart/form-data") in the server side.Do you have a sample code to handle and parse both text and byte[] messages in server side? If you have, would you mind share it with us?

MyDreamGirl

OK here is what I need from you:

  1. Create new thread
  2. Provide code that convert what ever data you sending to byte array
  3. Provide code that you use to transmit byte array to server
  4. Provide code if you have how you attempted to process byte array on server side

then we will take it from there.

can you write some program for ASCII converter?
please

can you write some program for ASCII converter?
please

Finished.

can you write some program for ASCII converter?
please

I will not write it as that is not my assignment, but you can do it and if you ask right questions you may get some help

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.