Search code examples
javaxmlsocketsunicodestax

Writing Stax XML to ObjectOutputStream(socket.getOutputStream) getting MalformedByteSequenceException


I'm trying to send an xml message to a server from a client app using sockets in Java but i don't know how to write it to the stream:

        String user = "Oscar"
        String pass = "1234"

        ObjectOutputStream oos = new ObjectOutputStream(
                socket.getOutputStream());

        // Create a XMLOutputFactory
        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();

        // Create XMLEventWriter
        XMLEventWriter eventWriter = outputFactory
                        .createXMLEventWriter(oos);

        // Create a EventFactory
        XMLEventFactory eventFactory = XMLEventFactory.newInstance();

        XMLEvent end = eventFactory.createDTD("\n");

        // Create and write Start Tag
        eventWriter.add(eventFactory.createStartDocument());
        eventWriter.add(end);

        //Se crean los atributos del tag
        ArrayList<Attribute> attributes = new ArrayList<Attribute>();
        attributes.add(eventFactory.createAttribute("nickname", user));
        attributes.add(eventFactory.createAttribute("password", pass));

        eventWriter.add(eventFactory.createStartElement
            ("", "", "authenticate",attributes.iterator(), null));
        eventWriter.add(end);

        eventWriter.add(eventFactory.createEndElement("", "", "authenticate"));

        eventWriter.add(eventFactory.createEndDocument());

should i use:

        eventWriter.flush();

?

if i do, it gives me the following exception:

javax.xml.stream.XMLStreamException: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 1 of 1-byte UTF-8 sequence.

It says i'm writing wrong the message. Then, What is the write way?

The message should be:

<?xml version="1.0" encoding="UTF-8"?>" +
<authenticate nickname="Oscar" password="1234" />

And here is the code i'm using at the server to read the message:

//the call
this.Interpreter.readCommand(socket.getInputStream());

and

//the method
@SuppressWarnings({ "unchecked", "null" })
public void readCommand(InputStream command) {

    try {

        // Fabrica de entrada de XML
        XMLInputFactory inputFactory = XMLInputFactory.newInstance();

        // Se crea un nuevo eventReader
        XMLEventReader eventReader = inputFactory.createXMLEventReader(command);

        while (eventReader.hasNext()) {

            XMLEvent event = eventReader.nextEvent();

            if (event.isStartElement()) {

                StartElement startElement = event.asStartElement();

                // Si tenemos un comando authenticate
                if (startElement.getName().getLocalPart().equals("authenticate")) {

                    CommandAuthenticate(startElement);
                }

            }

        }

    }
    catch (XMLStreamException e) {
        e.printStackTrace();
    }
}


public void CommandAuthenticate (StartElement startElement){


    String nickname = null;
    String password = null;

    // Se leen los atributos del comando
    Iterator<Attribute> attributes = startElement
                    .getAttributes();

    while (attributes.hasNext()) {

        Attribute attribute = attributes.next();

        if (attribute.getName().toString().equals("nickname")) {

            nickname = attribute.getValue();
        }

        if (attribute.getName().toString().equals("password")) {

            password = attribute.getValue();
        }

    }

    //here i call the right method for the data received

}

Solution

  • Don't use ObjectOutputStream. That's for serialization. You're not doing serialization. Just have the XMLEventWriter write directly to the socket's stream. Similarly, don't have an ObjectInputStream on the reading side.

    The reason this fails is that ObjectOutputStream adds a header to the stream, which the XML parser is choking on.