Think big but go small!

How I love this expression in “The One Thing”:

“Extraordinary results require you to go small.
Getting your focus as small as possible simplifies your thinking and crystallizes what you must do. No matter how big you can think, when you know where you’re going and work backwards to what you need to do to get there, you’ll always discover it begins with going small. Years ago, I wanted an apple tree on our property. Turns out you can’t buy a fully mature one. The only option I had was to buy a small one and grow it. I could think big, but I had no choice but to start small. So I did, and five years later we had apples. But because I thought as big as I could, guess what? You got it. I didn’t just plant one. Today—we have an orchard.”

Java: Retrieve/Merge pdfs from Urls (+bonus: fix certificate problem in HTTPS)

I introduce in this post the solution for the problem of retrieving multiple pdf files from Urls and of merging them into one unique pdf file. I will also show you how to avoid the certificate problem when retrieving pdf from Url.

As always, you can have many solutions for a specific problem. I use here iText for retrieving and merging pdfs from Urls.

  • Retrieving Pdf from Url by using PdfReader. The method retrieveSeuctityConnection uses the code from fix certificate HTTPS. It fixes the certificate problem in HTTPS (server requires certificate to be able to loading content)
private PdfReader retrievePdfReaderFromUrl(String url) {
 PdfReader reader = null;
 URL u = null;
 URLConnection urlConn = null;
 try
 {
     u = new URL(url);
     urlConn = u.openConnection();
 }
 catch (Exception e)
 {
    // exception while getting pdf
 }

 String contentType = urlConn != null
         && StringUtils.isNotEmpty(urlConn.getContentType())
         ? urlConn.getContentType() : " ";

 try
 {
      if (contentType.toLowerCase().indexOf("application/pdf") >= 0) {
            urlConn = retrieveSeuctityConnection(url);
            if (urlConn != null) {
                  reader = new PdfReader(urlConn.getInputStream());
            } else {
                  reader = null;
            }
      } else  {
            // the content is not pdf, do something
      }
 } catch (Exception e) {
      // exception while creating reader
 }
 return reader;
}

private URLConnection retrieveSeuctityConnection(String url) {
 try
 {
      /*
       * fix for Exception for Security Problem: PKIX path building failed
       */
      TrustManager[] trustAllCerts = new TrustManager[] {
          new X509TrustManager() {
               @Override
               public java.security.cert.X509Certificate[] getAcceptedIssuers()
               {
                   return null;
               }

               @Override
               public void checkClientTrusted(X509Certificate[] certs, String authType)
               {
               }

               @Override
               public void checkServerTrusted(X509Certificate[] certs, String authType)
               {
               }
           }
      };

      SSLContext sc = SSLContext.getInstance(SSL_CONTEXT);
      sc.init(null, trustAllCerts, new java.security.SecureRandom());
      HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

      // Create all-trusting host name verifier
      HostnameVerifier allHostsValid = new HostnameVerifier()
      {
              @Override
              public boolean verify(String hostname, SSLSession session)
              {
                  return true;
              }
      };
      // Install the all-trusting host verifier
      HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
      URL u = new URL(url);
      return u.openConnection();
 } catch (Exception e) {
     // exception while opening file in the given url
 }

 return null;
}
  • Merging PdfReaders to one unique pdf file
try {
 // create merged outputStream
 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 Document document = new Document();
 PdfCopy copy = new PdfSmartCopy(document, outputStream);
 document.open();
 for (String url : urlList)
 {
      PdfReader reader = retrievePdfReaderFromUrl(url);
      if (reader !=null) { // merge reader to output stream
            int n = reader.getNumberOfPages();
            for (int page = 0; page < n;) {
                copy.addPage(copy.getImportedPage(reader, ++page));
            }
            copy.freeReader(reader);
            reader.close();
      }
 }
 document.close();
 // The merged pdf is now available in  outputStream
} catch (Exception e) {
 // Exception while creating pdfs
}

HTH!

JavaMail Implementation with JBoss AS 7/ JBoss EAP 6

Many interesting posts can be found for Java Mail Implementation. Configuration for different JBoss versions including Java code for sending mail are well described in JBoss mail service configuration.

In this post, I will introduce the configuration for mail service in standalone.xml that can resolve the security problem of mail server certification. Popular exceptions fot this kind of bug:

javamail javax.mail.MessagingException: Could not convert socket to TLS;   nested exception is: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

or

com.sun.mail.smtp.SMTPSenderFailedException: 550 5.7.1 Client does not have permissions to send as this sender

The natural solution is to tell Java to trust all the servers to establish connection without certification (mail.smtp.ssl.trust=”*”). This can be done easily if your mail session with authorization information (username, password) is defined directly from Java codes. Typical mail session creation for SMTP Gmail:

Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com"); //use yours instead of gmail
props.put("mail.smtp.socketFactory.port", "465"); // your port 
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465"); // your port
props.put("mail.smtp.ssl.trust","*"); // accept all servers

Session session = Session.getDefaultInstance(props,
      new javax.mail.Authenticator() {
	   protected PasswordAuthentication getPasswordAuthentication() {
		return new PasswordAuthentication("username","password");
	   }
      });

It is more complex when your mail session is retrieved from the JBoss configuration file standalone.xml with  “smtp-server” tag. In my case, I replace “smtp-server” tag with “custom-server” with wide range of property configuration. Below is how my mail session looks like:

<mail-session name=”java:/MailSession” jndi-name=”java:/MailSession” from=”your@mail“>
<custom-server name=”smtp” tls=”true” outbound-socket-binding-ref=”mail-smtp-test”>
<login name=”your_user_name” password=”password“/>
                  <property name=”mail.smtp.ssl.trust” value=”*”/>
</custom-server>
<custom-server name=”test_property“>
                <property name=”test_val” value=”test”/>
         </custom-server>
</mail-session>

With “custom-server” tag, you can add any property you want to retrieve in Java. For example, to retrieve the value of test_property defined above:

((JavaMailSenderImpl) yourMailSender).getSession().getProperty(“mail.test_property.test_val“); // = “test”

HTH!

Configuring Multiple JBoss (EAP 6) Instances On One Machine (+Bonus IntelliJ Config)

This subject is well discussed on StackOverflow. Interesting answers for configuration tips (including jboss.socket.binding.port-offset,  socket-binding-group, jboss launcher creation, ..) can be found there:

http://stackoverflow.com/questions/21019860/configuring-multiple-jboss-7-instances-on-one-machine-how-to-run-at-a-time

In this post, I just describe how to configure you launcher with the same JBoss Server in IntelliJ.

First, we should create n copies of standalone (n number of project launchers) and rename to standalone1, standalone2, .., standalone_n.

Then, add “-Djboss.server.config.dir=” to your VM options to adapt each launcher as follows:

capture1

capture2

HTH!

 

Download/display Pdf/Excel from base64 string – byte array (+bonus IE workaround)

I introduce in this post how to display a pdf/excel base64 string retrieved from an ajax call (i.e Rest Controller – application/json). I will also present the solutions to make it work with different browsers (IE, Chrome, Firefox). Normally, IE often requires specific treatment than other browsers.

In my projects, the server side codes return some Java byte array (byte[]). For example:
– To generate byte array for pdf:

ByteArrayOutputStream byteStream = new ByteArrayOutputStream()
PdfWriter writer = PdfWriter.getInstance(document, byteStream);
.... // codes for generating pdf document
byte[] pdfBytes = byteStream.toByteArray();

– To generate byte array for excel:

HSSFWorkbook workbook = new HSSFWorkbook();
.... // codes for generating excel sheets
ByteArrayOutputStream bos = new ByteArrayOutputStream();
workbook.write(bos);
byte[] excelBytes = bos.toByteArray();

From the client side, it will generate a base64 string (application/json). Note that if you receive “xyz”, you should remove the first and last ” before treating the content.

var data = byteData.text().substring(1, byteData.text().length - 1); // remove the "" from your base64 string

Here are how to extract and display the document in browsers:

– To display/download pdf:

if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE workaround
            var byteCharacters = atob(data);
            var byteNumbers = new Array(byteCharacters.length);
            for (var i = 0; i < byteCharacters.length; i++) {
                byteNumbers[i] = byteCharacters.charCodeAt(i);
            }
            var byteArray = new Uint8Array(byteNumbers);
            var blob = new Blob([byteArray], {type: 'application/pdf'});
            window.navigator.msSaveOrOpenBlob(blob, your_file_name);
        }
        else { // much easier if not IE
            window.open("data:application/pdf;base64, " + data, '', "height=600,width=800");
        }

– To display/download excel:

if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE workaround
                var blob = this.createBlobFromString(data, 'application/vnd.ms-excel');
                window.navigator.msSaveOrOpenBlob(blob, your_file_name);
            } else { // other browers,  IE is easier in this case
                var blob = this.createBlobFromString(data, 'application/vnd.ms-excel');
                var url = URL.createObjectURL(blob);
                var dummyLink = document.createElement("a");
                dummyLink.href = url;
                dummyLink.download = your_file_name;
                document.body.appendChild(dummyLink);
                dummyLink.click();
            }

HTH!

iText large tables and dynamic page break

Dynamic page break management is often an uncomfortable task. In this post, I describe two solutions for dealing with such dynamic page breaks for two popular types of tables with large content.

  • Tables with large cell/row content: in case when your table may have a cell/row of two-page length. The solution is quite easy, just use the built-in treatment methods of PdfPtable: setSplitLate and setSplitRows as follows:            
yourTable.setSplitLate(false);
yourTable.setSplitRows(true);
  • Tables with huge number of rows (i.e: 3000 rows). In this case, the best solution is to write row by row and check the current cursor position to determine if you need to add manually a page break:
float currentPosition = your_start_position;
for (int rowIdx = 0; rowIdx < table.getRows().size(); rowIdx++) {
     currentPosition = table.writeSelectedRows(rowIdx, rowIdx + 1, marginLeft, currentPosition, cb);
     if (currentPosition < your_page_footer_height && rowIdx != table.getRows().size() - 1) {
                currentPosition = your_header_position - 10;
                document.newPage();
     }
}

HTH!

JfreeChart: two sided horizontal bar chart with custom item label

Many examples of horizontal bar JfreeChart are available to be consulted. However, these examples often create complicated bar chart (too much decors) and far from real business report needs.

In this post I will show you how to custom and simplify (no axis, no title, no legend) the standard horizontal bar chart with JfreeChart. I will focus on :

  1. Customizing the  space between bars and bar width (using BarRenderer – setMaximumBarWidth).
  2. Positioning the labels (outside the bars ItemLabelPosition)
  3. Creating a center line that separate the negative and positive bar on each row (add Maker to plot)

Bonus: an excellent work on bar chart margins and spacing can be found at:

http://stackoverflow.com/questions/16725545/closing-up-blank-space-in-jfreechart-bar-chart

Codes:

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Marker;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.ValueMarker;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.data.general.DefaultKeyedValues2DDataset;
import org.jfree.data.general.KeyedValues2DDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import org.jfree.ui.TextAnchor;

import java.awt.*;
import java.text.NumberFormat;

public class TwoSidedBarChartDemo extends ApplicationFrame {

 private static final long serialVersionUID = 1L;

 public TwoSidedBarChartDemo() {
      super(&quot;Two Sided Bar Chart Demo&quot;);
      KeyedValues2DDataset keyedvalues2ddataset = createDataset();

      // use stacked bar chart to have 2 columns on each row
      JFreeChart jfreechart = ChartFactory.createStackedBarChart(&quot;&quot;, &quot;&quot;, &quot;&quot;, keyedvalues2ddataset, PlotOrientation.HORIZONTAL,
false, false, false);
      jfreechart.setBackgroundPaint(new Color(255, 255, 255, 0));
      CategoryPlot plot = (CategoryPlot) jfreechart.getPlot();
      plot.setBackgroundPaint(Color.WHITE);
      plot.setOutlineVisible(false);
      plot.getDomainAxis().setVisible(false);
      plot.getRangeAxis().setVisible(false);

      // add 3 lines to the chart (1 black, 2 white) =&gt; seapration effect
      Marker marker = new ValueMarker(0);
      marker.setPaint(Color.black);
      marker.setStroke(new BasicStroke(2));
      plot.addRangeMarker(marker);

      marker = new ValueMarker(0.12);
      marker.setPaint(Color.WHITE);
      marker.setStroke(new BasicStroke(1.5f));
      plot.addRangeMarker(marker);

      marker = new ValueMarker(-0.12);
      marker.setPaint(Color.WHITE);
      marker.setStroke(new BasicStroke(1.5f));
      plot.addRangeMarker(marker);

      BarRenderer renderer = (BarRenderer) plot.getRenderer();
      renderer.setBarPainter(new StandardBarPainter());

     // ajust the bar width and spacing between bars
      renderer.setMaximumBarWidth(.03);

      // custom columns color
      renderer.setSeriesPaint(0, Color.RED);
      renderer.setSeriesPaint(1, Color.BLUE);

      renderer.setShadowVisible(false);
      renderer.setBaseItemLabelGenerator(
 new StandardCategoryItemLabelGenerator(
 &quot; {2} &quot;, NumberFormat.getInstance()));
      renderer.setBaseItemLabelsVisible(true);
      renderer.setBaseItemLabelPaint(Color.BLACK);

      // custom item labels position
      ItemLabelPosition p1 = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE11, TextAnchor.BASELINE_LEFT);
      renderer.setBasePositiveItemLabelPosition(p1);
      ItemLabelPosition p2 = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE1, TextAnchor.BASELINE_RIGHT);
      renderer.setBaseNegativeItemLabelPosition(p2);

      plot.getDomainAxis().setCategoryMargin(0.5);

      ChartPanel chartpanel = new ChartPanel(jfreechart);
      chartpanel.setPreferredSize(new Dimension(500, 270));
      setContentPane(chartpanel);
 }

 private KeyedValues2DDataset createDataset() {
     DefaultKeyedValues2DDataset defaultkeyedvalues2ddataset = new DefaultKeyedValues2DDataset();
     defaultkeyedvalues2ddataset.addValue(-6D, &quot;Negative&quot;, &quot;row 1&quot;);
     defaultkeyedvalues2ddataset.addValue(-8D, &quot;Negative&quot;, &quot;row 2&quot;);
     defaultkeyedvalues2ddataset.addValue(-11D, &quot;Negative&quot;, &quot;row 3&quot;);
     defaultkeyedvalues2ddataset.addValue(-13D, &quot;Negative&quot;, &quot;row 4&quot;);
     defaultkeyedvalues2ddataset.addValue(-14D, &quot;Negative&quot;, &quot;row 5&quot;);
     defaultkeyedvalues2ddataset.addValue(-15D, &quot;Negative&quot;, &quot;row 6&quot;);
     defaultkeyedvalues2ddataset.addValue(-19D, &quot;Negative&quot;, &quot;row 7&quot;);
     defaultkeyedvalues2ddataset.addValue(10D, &quot;Positive&quot;, &quot;row 1&quot;);
     defaultkeyedvalues2ddataset.addValue(12D, &quot;Positive&quot;, &quot;row 2&quot;);
     defaultkeyedvalues2ddataset.addValue(13D, &quot;Positive&quot;, &quot;row 3&quot;);
     defaultkeyedvalues2ddataset.addValue(14D, &quot;Positive&quot;, &quot;row 4&quot;);
     defaultkeyedvalues2ddataset.addValue(15D, &quot;Positive&quot;, &quot;row 5&quot;);
     defaultkeyedvalues2ddataset.addValue(17D, &quot;Positive&quot;, &quot;row 6&quot;);
     defaultkeyedvalues2ddataset.addValue(19D, &quot;Positive&quot;, &quot;row 7&quot;);
     return defaultkeyedvalues2ddataset;
 }

 public static void main(String args[]) {
     TwoSidedBarChartDemo chartdemo = new TwoSidedBarChartDemo();
     chartdemo.pack();
     RefineryUtilities.centerFrameOnScreen(chartdemo);
     chartdemo.setVisible(true);
 }
}

And here is how the chart looks like:

Capture

HTH!

Get strut2s action variable as JSON object (+convert to js object) using ajax invocation with jQuery

In this post, I will introduce how to retrieve data when invoking struts2 action using ajax (in your jQuery script).

Scenorio: I have an action class TestAction with an action (method) testRetrieveData to be invoked from jquery using ajax. When returning from testRetrieveData action, I would like to get a list of messages messList in TestAction.

Solution:

  • Config your action in struts-xml:

<action name=”testRetrieveData ” method=”testRetrieveData” class=”testActionClass”>

<result name=”testResult” type=”json”> // name: the result you return in testRetrieveData  methode – type=”json” => important to be able to retrieve in js

<param name=”noCache”>true</param> // standard
<param name=”enumAsBean”>true</param> // standard
<param name=”root”>messList </param> // important: the variable you want to retrieve in TestAction
<param name=”statusCode”>200</param>  // the request return code: 200 OK
</result>
</action>

  • Define the url for your action invocation using ajax (i.e in your page jsp)

<s:url var=”testGetMessList” action=’testRetrieveData’ namespace=’/YOUR/NAMSPACE’/>

var testGetMessListUrl = ‘<s:property value=”testGetMessList” />’;

  • Retrieve the message list with the ajax post using jQuery

$.ajax({url: testGetMessListUrl, success: function(result){
var messList = JSON.parse(result); // convert the list you want to get  to js object
}});

 

Easy right?

HTH

iText (AcroForms): multiple check boxes and click event detection

Yes, another iText post, I am more iText craft man this time 🙂

Not like radio buttons where you have one unique name for multiple radios and each time only one radio is checked. You have a small challenge with check boxes which allow multiple boxes to be checked at the same time. It is not quite easy to detect each time which box is checked.

In this post, I describe how to name each check box child; create  the click java script action and detect the name and content of the clicked check box. Not that when a check box is unchecked, its content (value) will be “Off”.

You find the code below:


package itext.examples;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.ColumnText;
import com.lowagie.text.pdf.GrayColor;
import com.lowagie.text.pdf.PdfAction;
import com.lowagie.text.pdf.PdfFormField;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.RadioCheckField;
import com.mainsys.itext.text.pdf.FieldUtils;

public class CheckBoxes {

void createDocument(String fileName)
throws IOException, DocumentException {
final Document document = new Document(PageSize.A4);
final PdfWriter writer = PdfWriter.getInstance(document, new                         FileOutputStream(fileName));
// page 1
document.open();

final float pageHeight = PageSize.A4.getHeight();

PdfFormField checkBoxes = PdfFormField.createCheckBox(writer);
// the general name for all check boxes, each child will have this as prefix
checkBoxes.setFieldName("CheckBoxContainer");

// creates 34check boxes
for (int i = 0; i &amp;lt; 4; i++)
{
Rectangle rectangle = new Rectangle(50f, pageHeight - 50f - i*20f, 60f, pageHeight - 60f - i*20f);
RadioCheckField radioCheckField = new RadioCheckField(writer, rectangle, "cb" + i, "check box " + i);
radioCheckField.setBorderColor(Color.GRAY);
radioCheckField.setBackgroundColor(GrayColor.GRAYWHITE);
radioCheckField.setCheckType(RadioCheckField.TYPE_CHECK);
PdfFormField pdfFormField = radioCheckField.getCheckField();
//add common action to each check box
pdfFormField.setAdditionalActions(PdfName.K,                                                   PdfAction.javaScript("toggleCheckBoxes(event)", writer));
checkBoxes.addKid(pdfFormField);

ColumnText.showTextAligned(writer.getDirectContent(),                                 Element.ALIGN_LEFT, new Phrase("check box " + i), 75f, pageHeight - 60f - i*20f, 0f);
}

writer.addAnnotation(checkBoxes);

// loads the java script action file
writer.addJavaScript("CheckBoxes",                                                                           loadJsResource("/js/CheckBoxAction.js"));

document.close();
}

/**
* Loads the string content from file
* @param resourceName
* @throws IOException
*/
private String loadJsResource(String resourceName)
throws IOException
{
InputStream inputStream =                                                                                           this.getClass().getResourceAsStream(resourceName);
String strRes = IOUtils.toString(inputStream, "UTF-8");
IOUtils.closeQuietly(inputStream);
return strRes;
}

public static void main(String[] args)
throws IOException, DocumentException
{
new CheckBoxes().createDocument("CheckBoxes.pdf");
}

}

Js action script


function toggleCheckBoxes(event) {
app.alert(event.target.name + " is clicked");
var idx = event.target.name.toString().replace("CheckBoxContainer.cb", "");
var content = this.getField("CheckBoxContainer.cb" + idx).value;
app.alert("The content is " + content);
}

And here is what you get as pdf file: CheckBoxes.pdf

Have fun!