0

I'm trying to zip a message (String) into a zip file, and then set it as the body of the exchange object in Apache Camel, so that one of the downstream services (also using Apache Camel) is able to extract the zip file using the exchange.getIn().getBody() method.

The first part is good, I'm able to set a zip file to the body, but when I try to retrieve this on the other side of the queue (Active MQ), the exchange.getIn().getBody(ZipFile.class) returns null. In fact, the body itself is null.

Why would that be?

I have tried sending a normal String in the body, and that worked fine. The File (ZipFile) doesn't set, wonder why.

Here are snippets of the code -

Route -

from(some_route)
.bean(SomeClass.class, "zipAndSend")
.to("activemq:queue:" + somequeue)

To zip a file -

public void zipAndSend(Exchange exchange) throws Exception {
        String incomingMessage;
        try {
            incomingMessage = exchange.getIn().getBody().toString();
            File file = ZipUtil.createFile(incomingMessage);
            String zipFilePath = file.getPath().replace(".xml", ".zip");
            ZipFile zipFile = ZipUtil.zipFile(file.getPath(), zipFilePath);

            exchange.getOut().setHeader("Compressed", "Y");
            exchange.getOut().setHeader("ZipFilePath", zipFilePath);
            exchange.getOut().setBody(zipFile);

//the body is set correctly here, so far so good

        } catch (Exception e) {
            e.printStackTrace(); //other operations


        }
    }

public static File createFile(String incomingMessaage) {

        String fileName = "C:\\Project\\ZipUnzipTest\\incoming.xml";
        File file = new File(fileName);
        try {
            FileUtils.writeStringToFile(file, incomingMessaage);
        } catch (Exception e) {
            //log.error("Error in Writing Message into file " + fileName, e);
            String errorFile = fileName.replace("work", "error");
        }
        return file;
    }

Over in the other service (end of the queue), I am overriding the process() method like below, to be able to extract the message (String) back from the file inside the zipped file.

public void process(Exchange exchange) throws WorkflowDBException,
            Exception {

        try {
            ZipFile zipFile = exchange.getIn().getBody(ZipFile.class); //NPE as body is null
            String zipFilePath = exchange.getIn().getHeader("ZipFilePath").toString();
            File inFile = ZipUtil.unzipFile(zipFile, "C:\\Project\\ZipUnzipTest\\Output\\WF", true);
            String incomingMessage;
            incomingMessage = FileUtils.readFileToString(inFile, "UTF-8");
} catch (Exception e) {e.printStackTrace();}
}

Dependencies -

<dependency>
            <groupId>net.lingala.zip4j</groupId>
            <artifactId>zip4j</artifactId>
            <version>1.3.2</version>
        </dependency>
<dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>

I expect the content of the body to be same in the in and out space. Alas, it isn't.

ok2c
  • 26,450
  • 5
  • 63
  • 71
GopherGopher
  • 376
  • 1
  • 2
  • 16
  • Apologies for the verbosity of the question - I'm new to Apache Camel so thought of putting as much out there as possible. – GopherGopher Aug 07 '19 at 07:13
  • I'm not so familiar with activemq, but maybe the queue you are sending to is only accepting textmessages not bytemessages? – soilworker Aug 07 '19 at 07:44
  • mmm try to log the body before the bean call, maybe the ZipClass lack an empty constructor? not sure how camel deserialize, maybe is not able to set the values. However why using the exchange the old way? You can do `public ZipFile zipAndSend(String body) {...return zipFile;}` and `public void process (ZipFile zipFile)` and let Camel do all the conversions and header magics – Paizo Aug 07 '19 at 09:01

1 Answers1

0

It turns out, Camel (amongst other frameworks) handles bytes[] rather well. I converted the ZipFile into a byte array, and used it to set the body of the exchange object.

incomingMessage = exchange.getIn().getBody().toString();
File file = ZipUtil.createFile(incomingMessage);
String zipFilePath = file.getPath().replace(".xml", ".zip");
ZipFile zipFile = ZipUtil.zipFile(file.getPath(), zipFilePath);
messageData = FileUtils.readFileToByteArray(new File(zipFilePath));

exchange.getOut().setHeader("Compressed", "Y");
exchange.getOut().setHeader("ZipFilePath", zipFilePath);
exchange.getOut().setBody(messageData);

And while reading it, I used the ZipInputStream to get the Zip Entry from the ByteArrayInputStream.

byte [] bytes = exchange.getIn().getBody(byte[].class);
ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(bytes));
try {
    StringBuilder s = new StringBuilder();
    StringBuilder temp = new StringBuilder();
    byte[] buffer = new byte[1024];
    int read = 0;
    ZipEntry entry;
    while ((entry = zipStream.getNextEntry())!= null) {
        while ((read = zipStream.read(buffer, 0, 1024)) >= 0) {
            s.append(new String(buffer, 0, read));
        }
        temp = temp.append(s);
        s.setLength(0);
    }
    return temp.toString();
} catch (Exception e) {
            e.printStackTrace();
}

Yes, that's it. Still open to other ways to solve this :)

GopherGopher
  • 376
  • 1
  • 2
  • 16