Convert String to a JMS BytesMessage in Java - java

I am trying to convert a String to a JMS BytesMessage. Is there a good way to do this?
I need to do this because I have a method that takes in a String that is decrypted and I need to convert it into a BytesMessage in order to decrypt the message.
Thanks

byte[] bArray = "foo".getBytes("UTF-8");
BytesMessage msg = session.createBytesMessage(); // throws JMSException
msg.writeBytes(bArray);
Of course, like Arcadien said, you need to execute the code in an appropriate environment to obtain the javax.jms.Session object from.

A bit late,
but better late than never.
The #Carlo answer is essentially correct,
except that you must catch an exception if you use getBytes
with a String parameter.
Here is a variation (of the getBytes call) that will not throw an exception:
final byte[] byteArray = "blammy".getBytes(StandardCharsets.UTF_8);
final BytesMessage bytesMessage = session.createBytesMessage();
bytesMessage.writeBytes(byteArray);
The StandardCharsets class defines charsets that are guaranteed to be available on every implementation of the Java platform.

you can use
byte[] String#getBytes()
to get a byte array from a string and write it to a ByteMessage

Related

Send Data between client and server as a byte array

I am trying to send encrypted data between a client and server. Due to the RSA encryption its in Byte array form. This means I have had to change the way I send data. I curently cant get it working, Ill leave my method (sendMessage) below which is what handles the sending of the message, If anyone could tell me what I am doing wrong that would be great :)
public void sendMessage(byte[] msg){
if(msg.equals("null")){
}
else{
try{
ByteArrayOutputStream f = new ByteArrayOutputStream(CSocket.getOutputStream());
out = new PrintWriter(f);
out.write(msg);
countSend++;
}catch (IOException e){
System.out.println("ERROR");
}
}
}
Sorry should have clarified, essentially CSocket is a socket I have opend and I want to send msg through the socket. The issue I have specifically with this code is It says that: OutputStream can not be converted to int on the line where I creat the ByteArrayOutputStream object f and No suitable method found for write(byte[]) on the line out.write(msg);
Thanks for the clarification! Please see https://docs.oracle.com/javase/10/docs/api/java/io/ByteArrayOutputStream.html#write(byte%5B%5D,int,int)
The write method in ByteArrayOutputStream for byte[] needs two more arguments. Something like the following might work:
out.write(msg, 0, msg.length);
Please let me know if this is useful.
I think I fixed my issue now. Its probibably not the most efficient way of doing it but essentially I encode the byte array in a format that means I wont loose any data. This means I send it in this encoded format and then on the receving end I just simply decode it. Works so much better with print writer doing it this way.
OutputStream f = CSocket.getOutputStream();
out = new PrintWriter(f);
String encodedmsg = new String(msg, "ISO-8859-1"); // ISO-8859-1 is supposed to give every character a unique representation so I shouldent loose any data during encoding and decoding
out.write(encodedmsg);

Converting string to byte[] returns wrong value (encoding?)

I read a byte[] from a file and convert it to a String:
byte[] bytesFromFile = Files.readAllBytes(...);
String stringFromFile = new String(bytesFromFile, "UTF-8");
I want to compare this to another byte[] I get from a web service:
String stringFromWebService = webService.getMyByteString();
byte[] bytesFromWebService = stringFromWebService.getBytes("UTF-8");
So I read a byte[] from a file and convert it to a String and I get a String from my web service and convert it to a byte[]. Then I do the following tests:
// works!
org.junit.Assert.assertEquals(stringFromFile, stringFromWebService);
// fails!
org.junit.Assert.assertArrayEquals(bytesFromFile, bytesFromWebService);
Why does the second assertion fail?
Other answers have covered the likely fact that the file is not UTF-8 encoded giving rise to the symptoms described.
However, I think the most interesting aspect of this is not that the byte[] assert fails, but that the assert that the string values are the same passes. I'm not 100% sure why this is, but I think the following trawl through the source code might give us the answer:
Looking at how new String(bytesFromFile, "UTF-8"); works - we see that the constructor calls through to StringCoding.decode()
This in turn, if supplied with tht UTF-8 character set, calls through to StringDecoder.decode()
This calls through to CharsetDecoder.decode() which decides what to do if the character is unmappable (which I guess will be the case if a non-UTF-8 character is presented)
In this case it uses an action defined by
private CodingErrorAction unmappableCharacterAction
= CodingErrorAction.REPORT;
Which means that it still reports the character it has decoded, even though it's technically unmappable.
I think this means that even when the code gets an umappable character, it substitutes its best guess - so I'm guessing that its best guess is correct and hence the String representations are the same under comparison, but the byte[] are no longer the same.
This hypothesis is kind of supported by the fact that the catch block for CharacterCodingException in StringCoding.decode() says:
} catch (CharacterCodingException x) {
// Substitution is always enabled,
// so this shouldn't happen
I don't understand it fully, but here's what I get so fare:
The problem is that the data contains some bytes which are not valid UTF-8 bytes as I know by the following check:
// returns false for my data!
public static boolean isValidUTF8(byte[] input) {
CharsetDecoder cs = Charset.forName("UTF-8").newDecoder();
try {
cs.decode(ByteBuffer.wrap(input));
return true;
}
catch(CharacterCodingException e){
return false;
}
}
When I change the encoding to ISO-8859-1 everything works fine. The strange thing (which a don't understand yet) is why my conversion (new String(bytesFromFile, "UTF-8");) doesn't throw any exception (like my isValidUTF8 method), although the data is not valid UTF-8.
However, I think I will go another and encode my byte[] in a Base64 string as I don't want more trouble with encoding.
The real problem in your code is that you don't know what the real file encoding.
When you read the string from the web service you get a sequence of chars; when you convert the string from chars to bytes the conversion is made right because you specify how to transform char in bytes with a specific encoding ("UFT-8"). when you read a text file you face a different problem. You have a sequence of bytes that needs to be converted to chars. In order to do it properly you must know how the chars where converted to bytes i.e. what is the file encoding. For files (unless specified) it's a platform constants; on windows the file are encoded in win1252 (which is very close to ISO-8859-1); on linux/unix it depends, I think UTF8 is the default.
By the way the web service call did a decond operation under the hood; the http call use an header taht defins how chars are encoded, i.e. how to read the bytes form the socket and transform then to chars. So calling a SOAP web service gives you back an xml (which can be marshalled into a Java object) with all the encoding operations done properly.
So if you must read chars from a File you must face the encoding issue; you can use BASE64 as you stated but you lose one of the main benefits of text files: the are human readable, easing debugging and developing.

MalformatedInputException with Utility.convertByteArrayToCharArray and MessageDigest

I'm trying to create a glassfish custom JDBCRealm and during some test on it, I got a MalformatedInputException when I using the com.sun.enterprise.util.Utility.convertByteArrayToCharArray function.
So I decided to externalize the part of my function which throw this error to test it and understand where it comming.
Resumed function:
public void justATestFunction()
throws Exception
{
final char[] password = "myP4ssW0rd42".toCharArray();
MessageDigest md = MessageDigest.getInstance("SHA-256");
// according to the Utility doc, if the Charset parameter is null or empty,
// it will call the Charset.defaultCharset() function to define the charset to use
byte[] hashedPassword= Utility.convertCharArrayToByteArray(password, null);
hashedPassword = md.digest(hashedPassword);
Utility.convertByteArrayToCharArray(hashedPassword, null); // throw a MalformatedInputException
}
Thank you in advance for your answer.
Let's look at each step:
byte[] hashedPassword= Utility.convertCharArrayToByteArray(password, null);
The above converts the Unicode-16 characters to a byte-array using the default endcoding, probably WIN-1252 or UTF-8. Since the password contains nothing outside standard 7-bit ASCII, the result is the same for either encoding.
hashedPassword = md.digest(hashedPassword);
hashedPassword now refers to a completely different byte array containing the BINARY digest of the original password. This is a BINARY string and no longer represents anything in any character encoding. It is pure binary data.
Utility.convertByteArrayToCharArray(hashedPassword, null);
Now you attempt to "decode" the binary string as if it were encoded with the default character set, which will undoubtedly throw an exception.
I suspect you really wanted to display either the hexadecimal representation of the digest, or maybe the base-64 version. In either case, what you have done will never work.
Since you haven't explained what you want to accomplish, this is the best anyone can do.

getBytes then toString don't give the same result each time

I am trying to use the sample BlueToothChat of Android but there is something I don't understand :
byte[] send = message.getBytes();
Log.d("SEND_BYTE", send.toString());
mChatService.write(send);
Here, message is a String, which is then converted to bytes, I guess in order to be sent. But When I check the log, the send.toString() part is really short even if the message I type is long. Worse, if I type twice the same message, I get 2 different logs, which is really weird I find.
Here is what I get in the log for the message hello, three times in a row :
[B#413d62e0
[B#41390078
[B#413ed3d8
There must be something (maybe really simple) I didn't get, but can(t figure out what it is. Can you help me with this?
Edit :
Maybe it is useful to add the following of the code, so here is the complete code :
byte[] send = message.getBytes();
Log.d("SEND_BYTE", send.toString());
mChatService.write(send);
// Reset out string buffer to zero and clear the edit text field (buffer is used in the write function)
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
Yes, calling toString() on a byte array is a bad idea. Arrays don't override toString(), so you get the default behaviour of Object.toString().
To reverse the String.getBytes() call, you want:
Log.d("SEND_BYTE", new String(send));
Or to see the bytes more directly:
Log.d("SEND_BYTE", Arrays.toString(send));
However, I would strongly encourage you not to do that directly. Instead, you should specify an encoding when you convert to or from binary, otherwise it will use the platform default encoding. What encoding is the chat service expecting? For example, if it's expecting UTF-8:
byte[] send = message.getBytes("UTF-8");
Log.d("SEND_BYTE", Arrays.toString(send));
mChatService.write(send);
You need to create a new string object to get the actual string
String senddata=new String(send);
Try:
Log.d("SEND_BYTE", new String(send, "UTF-8"););

Protocol Buffer: From Java to Objective-C using byte[]

I am currently using google's protocol buffers. It works painlessly between Java and C#, however I am running into problems trying to achieve the same use with Obj-c.
The Java WS returns a byte[]. The code that uses the protocol buffer API is simple enough:
productGroup.toByteArray();
I am able to recreate the object with Skeet's C# port, using:
byte[] result = searchWebService.SearchProductsProtocolBuffer(search);
ProductProtoGroup products = ProductProtoGroup.ParseFrom(result);
However, on the obj-c side, I am struggling to work with the return value.
The NSString I receive from the same web service RPC is this:
CmYKEzgwMDAwMUFELTEzMjUyNzk5MTQySUZPT0QgJiBCRV...
I'm not quite sure what to do with this, because I don't know what it is, save it was generated from an array of bytes. I tried parsing it directly to NSData using
NSData* data = [returnValue dataUsingEncoding:NSUTF8StringEncoding];
but on [ProductProtoGroup parseFromData:data];, I get an InvalidProtocolBuffer
I've checked on the Java side what byte string/hexadecimal representations of the original byte[], and it doesn't match the string I receive from the ws.
Hexadecimal is 0-F. Perhaps each byte was converted to a char? No, that doesn't match.
Any help would be appreciated.
Dane
With a fresher mind and some helpful comments, I finally got it.
I was wondering how the web service automagically sent a byte[] in Java, then reconstructed it in C# later, and also how to store this message later.
Turns out the string,
CmYKEzgwMDAwMUFELTEzMjUyNzk5MTQySUZPT0QgJiBCRV...
was indeed what was being sent in the soap envelopes. So inbetween creation of a byte[] in Java and transmission, something was happening. Looking at the message handler in C#,
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("",
RequestNamespace="x", ResponseNamespace="x",
Use=System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("return",
Form=System.Xml.Schema.XmlSchemaForm.Unqualified,
DataType="base64Binary", IsNullable=true)]
public byte[] searchProductProtocolBuffer([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] string arg0)
{
object[] results = this.Invoke("searchProductProtocolBuffer", new object[] {
arg0});
return ((byte[])(results[0]));
}
So base64Binary!, which I admittedly am meeting for the first time. Poking around, Skeet says it is the safest way:
How can I safely convert a byte array into a string and back?
So, knowing the encoding, the solution becomes straight forward. Using the algorithm presented in an answer to this question: How do I do base64 encoding on iphone-sdk?, my final code becomes:
NSString* returnValue = [WebServiceUtil processStringReturnValue:value];
NSData* data = [Encoding base64DataFromString:returnValue];
ProductProtoGroup* products = [ProductProtoGroup parseFromData:data];
I know very little about Objective C, but an NSString is no byte array. Have you tried converting the NSString to char* using -[NSString UTF8String]?

Categories

Resources