I have a method like this
private byte[] getInternalMDPayload(String metaDataDirString)
{
byte[] data = new byte[16384];
try
{
final InputStream internalMetadataInputStream = this.getClass().getClassLoader()
.getResourceAsStream(metaDataDirString);
data = ByteStreams.toByteArray(internalMetadataInputStream);
byteString = ByteString.copyFrom(data);
} catch (IOException e)
{
dl.debug("Error occurred while loading the metadata file" + metaDataDirString);
}
}
Is there any way to mock these objects?
Currently i am using #Mocked final Process mockProcess to mock the input stream couldn't able to find out how to mock ByteString and byte[].
I would go with this:
Mockito
.when(ByteString.copyFrom(Mockito.<byte[]>any()))
.thenReturn(ByteString.copyFromUtf8("byteString was mocked"));
Related
I'm trying to convert a byte array to a PDF document, but the the PDF file seems to be corrupted. And if open the file with a text reader the file just say "Undefined" I have searched through various stack topics but no luck. And the way i do it should work according to other topics. Below is my code. The code is executed trough a rest controller. Would really appreciate if someone could help me :).
//Controller
#ResponseBody
#RequestMapping(value = "/orders/{orderCode}/receipt", method = RequestMethod.GET, produces = "application/pdf")
public void getOrderReceiptConroller(#PathVariable("orderCode") final String orderCode, final HttpServletResponse response)
{
response.setContentType(CoreConstants.MIME_TYPE_APPLICATION_PDF);
final InputStream inputStream = new ByteArrayInputStream(OrderFacade.getReceiptPdf(orderCode));
OutputStream outputStream = null;
try
{
outputStream = response.getOutputStream();
IOUtils.copy(inputStream, outputStream);
}
catch (final IOException e)
{
}
finally
{
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
}
}
// calls this code that returns the byteArray.
private byte[] getReceiptPdf()
{
Gson gson = new Gson();
Edwresults edwResult = gson.fromJson(new FileReader(mockResponsePath), Edwresults.class);
String response = edwResult.getResults().get(0).getData().get(0).getDigitalReceipt();
byte[] byteData = response.getBytes();
return byteData;
}
I am trying to mock a function that is being called within another function. But I am getting end result as null. I tried to mock the second function that is being used in actual function.
Here is my code:
#RunWith(MockitoJUnitRunner.class)
public class LoadJsonData_Test {
#Mock
LoadJsonData loadJsonData;
#Test
public void getChartTypeJS_test() {
String jsonStr = "";
try {
InputStream is = this.getClass().getClassLoader().getResourceAsStream("chartInfo.json");
int size = is.available();
byte[] buffer = new byte[size];
if (is.read(buffer) > 0)
jsonStr = new String(buffer, "UTF-8");
is.close();
} catch (IOException ex) {
ex.printStackTrace();
}
when(loadJsonData.getJsonData()).thenReturn(jsonStr);
System.out.println(loadJsonData.getJsonData()); //Printing the data I wanted
assertEquals(loadJsonData.getChartTypeJS(),
"javascript:setChartSeriesType(%d);"); // loadJsonData.getChartTypeJS() returns null
}
Code I am trying to test:
public String getJsonData() {
try {
InputStream is = mContext.getAssets().open("chartInfo.json");
int size = is.available();
byte[] buffer = new byte[size];
if (is.read(buffer) > 0)
jsonString = new String(buffer, "UTF-8");
is.close();
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
return jsonString;
}
public String getChartTypeJS() {
jsonString = getJsonData();
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONObject javascriptEvent_JsonObject = jsonObject.getJSONObject("javascript_events");
return javascriptEvent_JsonObject.getString("chartType");
} catch (JSONException e) {
e.printStackTrace();
}
return "";
}
What is it I am doing wrong?
Thanks
You are mocking LoadJsonData and then invoking two methods on it:
getJsonData()
getChartTypeJS()
You create an expectation on the response from getJsonData() here:
when(loadJsonData.getJsonData()).thenReturn(jsonStr);
But since the mock has no expectation for a response from getChartTypeJS() this invocation returns null: loadJsonData.getChartTypeJS().
It looks like LoadJsonData should be a Spy not a Mock since that would allow you to mock getJsonData() but invoke the actual implementation of getChartTypeJS().
For example:
#Spy
LoadJsonData loadJsonData;
// this wil tell Mockito to return jsonStr when getJsonData() is invoked on the spy
doReturn(jsonStr).when(loadJsonData.getJsonData());
// this will invoke the actual implementation
assertEquals(loadJsonData.getChartTypeJS(), "javascript:setChartSeriesType(%d);");
More details on spying (aka partial mocks) here.
I've used an ExceptionMapper on the server side, putting the custom exception in the Response's body. How can I retrieve the original exception on the client side, and throw it to the caller?
You can serialize the exception and include it as a part of the response:
public final class SerializingExceptionMapper implements ExceptionMapper<Exception> {
#Override
public Response toResponse(Exception exception) {
try {
final byte[] serializedException = serializeException(exception);
final String base64EncodedException = Base64.getEncoder().encodeToString(serializedException);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new Message(base64EncodedException))
.build();
} catch (Exception ex) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
private byte[] serializeException(Exception ex) throws IOException {
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
final ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(ex);
oos.close();
return bos.toByteArray();
}
}
final class Message {
public Message(String exception) {
this.exception = exception;
}
public String exception;
}
Then on the client side you should do just the opposite:
Unmarshal the (maybe JSON) response
Decode the base64 encoded exception to a byte[]
De-serialize the exception
Create a ByteArrayInputStream
Create ObjectInputStream
Just readObject() the exception
Do whatever you want with it on the client side
PS: This can be achieved without any buffering (i.e. without the byte[]s) -> just use a StreamingOutput as .entity() and write to the provided output stream instead of a ByteArrayOutputStream. The same applies for deserialization on the client side.
I wrote a custom serializing/de-serializing logic for persisting some of the data as Java default serialization turned out to be both time and memory expensive. For this purpose I wrote readObject(ObjectInput in) and writeObject(ObjectOutput out) methods for the class(es) that needs persisting. However I noticed that if I do not use any out.writeObject(obj) in writeObject(ObjectOutput out) method then it always throws EOFException.
Consider the following example:
Data.java
public class Data implements BaseData {
private String messageUID;
private String rawData;
private String data;
private Long type;
private Boolean processed = false;
private String processedMessage;
private String processedDetaildMessage;
// getter setter
public void readObject(ObjectInput in) throws IOException, ClassNotFoundException {
messageUID = in.readUTF();
rawData = in.readUTF();
data = in.readUTF();
type = in.readLong();
processed = in.readBoolean();
if (processed) {
processedMessage = in.readUTF();
processedDetaildMessage = in.readUTF();
}
}
public void writeObject(ObjectOutput out) throws IOException {
out.writeUTF(messageUID);
out.writeUTF(rawData);
out.writeUTF(data);
out.writeLong(type);
out.writeBoolean(processed);
if (processed) {
out.writeUTF(processedMessage);
String tempDetailsMessage[] = processedDetaildMessage.split(" more");
out.writeUTF(tempDetailsMessage[tempDetailsMessage.length - 1]);
}
}
However whenever I use above code the out stream is always missing some information at the end (from processedDetaildMessage field) and I get EOFException while reading it form in, stacktrace below (Data.java line 216 is processedDetaildMessage = in.readUTF());
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.readByte(ObjectInputStream.java:2766)
at java.io.ObjectInputStream$BlockDataInputStream.readUTFChar(ObjectInputStream.java:3158)
at java.io.ObjectInputStream$BlockDataInputStream.readUTFBody(ObjectInputStream.java:3055)
at java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:2864)
at java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1072)
at com.smartstream.common.Data.readObject(Data.java:216)
at com.smartstream.common.PerformanceTest.getObjectFromBytes(PerformanceTest.java:168)
at com.smartstream.common.PerformanceTest.access$0(PerformanceTest.java:160)
at com.smartstream.common.PerformanceTest$1.mapRow(PerformanceTest.java:119)
at com.smartstream.common.PerformanceTest$1.mapRow(PerformanceTest.java:1)
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:92)
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:60)
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:651)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:639)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:668)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:676)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:731)
at com.smartstream.common.PerformanceTest.readFromDb(PerformanceTest.java:109)
at com.smartstream.common.PerformanceTest.main(PerformanceTest.java:66)
so I though I would put some extra byte/s of information at the end after writing all required fields and will not read them so that I don't reach end of file while reading. I tried all of these out.writeByte(-1), out.writeInt(-1), out.writeLong(2342343l), out.writeUTF("END_OF_STREAM") but those make no difference. finally I did this out.writeObject(new String("END_OF_STREAM")) and it works fine. Can someone please explain as to why outputstream misses some information if none of the information is written using writeObject() method. Below is how I read and write to/from streams;
private byte[] getObjectAsBytes(Data data) {
byte[] byteArray = null;
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
// Use this for java default serialization
// oos.writeObject(data);
data.writeObject(oos);
byteArray = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.flush();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return byteArray;
}
private Data getObjectFromBytes(byte[] byteArray) {
Data data = new Data();
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
bais = new ByteArrayInputStream(byteArray);
ois = new ObjectInputStream(bais);
// Use this for java default serialization
// data = (Data) ois.readObject();
data.readObject(ois);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return data;
}
If anyone is interested below is what is written in the streams;
persisted data with original code (throws EOFException and missing information) (don't confuse the stacktrace with original issue this stacktrace is persisted as field processedDetailedMessage)
¬í---z-------3507319347632941385----FEEDER-----1437052314954 ---This is a random string---N---þ%J---!this is message of processed dataÛ
Caused by: java.sql.SQLException: ORA-01691: unable to extend lob segment TLM_DBO.SYS_LOB0000076335C00008$$ by 8192 in tablespace WIN_SL_TABLE
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1008)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
at oracle.jdbc.driver.OraclePre
persisted data after writing extra string at the end using writeObject method
¬í---z-------3507319347632941385----FEEDER-----1437052314954 ---This is a random string---N---þ%J---!this is message of processed dataÛ
Caused by: java.sql.SQLException: ORA-01691: unable to extend lob segment TLM_DBO.SYS_LOB0000076335C00008$$ by 8192 in tablespace WIN_SL_TABLE
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1008)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
at oracle.jdbc.driver.OraclePrz-----NeparedStatement.execute(OraclePreparedStatement.java:3550)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1374)
at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.pmiExecute(WSJdbcPreparedStatement.java:975)
at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.execute(WSJdbcPreparedStatement.java:642)
at com.smartstream.control.engine.config.dao.jdbc.ProcessExecutionAuditDetailDao$1.doInPreparedStatement(ProcessExecutionAuditDetailDao.java:115)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:586)
... 23t
END_OF_STREAM
PS ---- represents unreadable bytes
Your persisted data is incomplete because you are creating your byte array before flushing the ObjectOutputStream. In getObjectAsBytes(Data) move byteArray = bos.toByteArray(); after the finally block to make it work. Alternatively, the method could be written more succinctly as follows (requires Java 7+):
private byte[] getObjectAsBytes(Data data) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
data.writeObject(oos);
} catch (IOException e) {
e.printStackTrace();
}
return bos.toByteArray();
}
I tested both ways in my own program and they both prevent the EOFException from being thrown.
As far as why having a writeObject was working, that's because the underlying writeObject implementation toggles block data mode at the beginning and ending of the method, and changing the block data mode performs a drain which writes all data to the underlying OutputStream, which for a ByteArrayOutputStream is effectively the same as a flush.
This issue is caused because of the different implementations of writeObject method and some other non-generic write* methods i.e. writeUTF. The writeObject method toggles to data block mode at the start and at the end of the method which results all the data being written to underlying OutputStream, this has same affect as calling flush on outputStream. This means that you cannot create another byteArray before flushing the remaining data to the stream. It would be best if you stick with writeObject method for now; ie
public void writeObject(ObjectOutput out) throws IOException {
out.writeUTF(messageUID);
out.writeUTF(rawData);
out.writeUTF(data);
out.writeLong(type);
out.writeBoolean(processed);
if (processed) {
out.writeUTF(processedMessage);
String tempDetailsMessage[] = processedDetaildMessage.split(" more");
out.writeObject(tempDetailsMessage[tempDetailsMessage.length - 1]);
}
}
To validate the api key I have employed ContainerRequestFilter to read the JSON payload and parse the api key. I have following method.
public ContainerRequest filter(ContainerRequest request) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = request.getEntityInputStream();
try {
int read;
final byte[] data = new byte[2048];
while ((read = in.read(data)) != -1)
out.write(data, 0, read);
byte[] requestEntity = out.toByteArray();
request.setEntityInputStream(new ByteArrayInputStream(requestEntity));
if (!validate(new String(data))) {
throw new WebApplicationException(401);
}
return request;
} catch (IOException ex) {
throw new WebApplicationException(401);
}
}
However, the data is getting always blank/empty. Without the filter the payload reaches the resource class and works just fine. Any clues as to why the payload is empty? I was testing this with Firefox's REST Client with JSON in the Body.
I assume you want to call
validate(new String(requestEntity))
instead of
validate(new String(data))
because in the second case you can get an invalid JSON (if your payload is big enough).
Also you might want to consider using MessageBodyReaders to read your entity for you:
public ContainerRequest filter(ContainerRequest request) {
// Buffer
InputStream in = request.getEntityInputStream();
if (in.getClass() != ByteArrayInputStream.class) {
// Buffer input
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ReaderWriter.writeTo(in, baos);
} catch (IOException ex) {
throw new ContainerException(ex);
}
in = new ByteArrayInputStream(baos.toByteArray());
request.setEntityInputStream(in);
}
// Read entity as a string.
final String entity = request.getEntity(String.class);
if (!validate(entity) {
throw new WebApplicationException(401);
}
// Reset buffer
ByteArrayInputStream bais = (ByteArrayInputStream)in;
bais.reset();
return request;
}
The only thing I can think of is that, somehow, the input stream is being read before your filter gets the ContainerRequest. Are there any other classes that still read in the data or is your Jersey setup somehow misconfigured so that the resource class is reading the input stream before your filter?