{"id":18,"date":"2003-11-04T22:15:02","date_gmt":"2003-11-05T04:15:02","guid":{"rendered":"http:\/\/www.mooreds.com\/wordpress\/?p=18"},"modified":"2003-11-04T22:15:02","modified_gmt":"2003-11-05T04:15:02","slug":"sending-binary-data-via-struts","status":"publish","type":"post","link":"https:\/\/www.mooreds.com\/wordpress\/archives\/18","title":{"rendered":"Sending Binary Data Via Struts"},"content":{"rendered":"<p><a href='http:\/\/jakarta.apache.org\/struts\/'>Struts<\/a> is a MVC web framework. It allows you to specify the paths through a web application in an XML configuration file, and provides some nice tag libraries for JSP manipulation.  The views for the states are usually JSPs, and the controller is a servlet provided for you.<\/p>\n<p>\nThis standard setup is fine, most of the time.  But I&#8217;ve run into situations, as have others (<a href='http:\/\/groups.google.com\/groups?hl=en&amp;lr=lang_en&amp;ie=UTF-8&amp;oe=UTF-8&amp;safe=off&amp;selm=bi2q4f%24t8m%241%40oravannahka.helsinki.fi'>1<\/a>,<a href='http:\/\/nagoya.apache.org\/eyebrowse\/ReadMsg?listName=struts-user@jakarta.apache.org&amp;msgId=748268'>2<\/a>), where you need Struts to output a binary file.  In my case, I&#8217;m sending a dynamic image to a non browser client, and I basically need to write a <a href='http:\/\/java.sun.com\/j2se\/1.4.2\/docs\/api\/java\/io\/ByteArrayOutputStream.html'>ByteArrayOutputStream<\/a> to the response output stream.<\/p>\n<p>\nNow, you&#8217;d think I&#8217;d be able to do this with a JSP.  After all, a JSP is just a servlet turned inside out, right?  Well, according to the specification, you&#8217;d be right.  From page 42 of JSP 1.2 spec:<\/p>\n<p>\n&#8212;&#8212;&#8212;&#8212;&#8212;-<br \/>\nThe JSP container should not invoke response.getWriter() until the time when the first portion of the content is to be sent to the client. This enables a number of uses of JSP, including using JSP as a language to  glue actions that deliver binary content, or reliably forwarding to a servlet, or change dynamically the content type of the response before generating content. See Chapter JSP.3.<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;-<\/p>\n<p>\nBut, according to Tomcat 4.1.24 on the Linux platform, you&#8217;d be wrong. When calling &#8216;java.io.OutputStream rs = response.getOutputStream();&#8217; in my JSP, I get this code generated:<\/p>\n<p>\n&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<pre>\n....snip...\n      application = pageContext.getServletContext();\n      config = pageContext.getServletConfig();\n      session = pageContext.getSession();\n      out = pageContext.getOut();\n      _jspx_out = out;\njava.io.OutputStream rs = response.getOutputStream();\n....snip...<\/pre>\n<p>\n&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<p>\nThe JSP is taking my stream before my code has a chance.  Therefore, I get an &#8220;getOutputStream() has already been called for this response&#8221; error. The weird bit is that this doesn&#8217;t seem to happen on Tomcat 4.1.24 on Windows (same version of struts).<\/p>\n<p>\nSo, what do you do?  You write a servlet instead.  That way you have utter control over the output stream:<\/p>\n<p>\n&#8212;&#8212;&#8212;&#8212;&#8212;<br \/>\n<\/p>\n<pre>\nimport javax.servlet.http.*;\nimport javax.servlet.*;\nimport java.io.*;\n\npublic class BinaryStreamServlet extends HttpServlet {\n\n   public void service(HttpServletRequest req, HttpServletResponse res)\nthrows ServletException, IOException {\n      String contentType =\n(String)req.getAttribute(\"contentType\");\n      if (contentType == null || \"\".equals(contentType)) {\n         contentType = \"image\/png\"; \/\/ default\n      }\n      res.reset();\n      res.setContentType(contentType);\n      OutputStream sos = res.getOutputStream();\n      ByteArrayOutputStream baos = (ByteArrayOutputStream)req.getAttribute(\"baos\");\n      baos.writeTo(sos);\n   }\n}<\/pre>\n<p>\n&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<p>\nI set up my action classes to cache the ByteArrayOutputStream in the request, with the name &#8220;baos.&#8221;  I added these lines to my web.xml:<\/p>\n<p>\n&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<pre>&lt;servlet&gt;\n      &lt;servlet-name&gt;binaryFileServlet&lt;\/servlet-name&gt;\n       &lt;servlet-class&gt;BinaryStreamServlet&lt;\/servlet-class&gt;\n  &lt;\/servlet&gt;\n....snip...\n  &lt;servlet-mapping&gt;\n    &lt;servlet-name&gt;binaryFileServlet&lt;\/servlet-name&gt;\n    &lt;url-pattern&gt;\/binaryFile&lt;\/url-pattern&gt;\n  &lt;\/servlet-mapping&gt;<\/pre>\n<p>\n&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<p>\nand this to my struts-config.xml for any actions that needed to be able to send binary data:<\/p>\n<p>\n&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<pre>\n&lt;forward name=\"success\"         path=\"\/binaryFile\"\/&gt;<\/pre>\n<p>\n&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<p>\nWorks like a charm.  Leave the JSPs to the character data, and use this simple servlet for binary delivery.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Struts is a MVC web framework. It allows you to specify the paths through a web application in an XML configuration file, and provides some nice tag libraries for JSP [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-18","post","type-post","status-publish","format-standard","hentry","category-java"],"_links":{"self":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts\/18","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/comments?post=18"}],"version-history":[{"count":0,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts\/18\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/media?parent=18"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/categories?post=18"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/tags?post=18"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}