Apache Utilities at Work Tom Marrs
May 10, 2015
Apache Utilities at Work
Tom Marrs
2 © 2008 CIBER, Inc. All rights reserved
Who am I?
• Background– Co-author of JBoss At Work: A Practical Guide
(O’Reilly, November 2005)• Currently working on 2nd ed.
– User Groups• Founding President of DOSUG
• Past President of DJUG
– Related Experience• I’ve been on several bad projects
• I hate re-inventing the wheel
3 © 2008 CIBER, Inc. All rights reserved
Learning Objectives
• As a result of this presentation you will learn:– To research Open Source utilities before coding– To avoid re-inventing the wheel– What common utilities are available on Apache– How to use Apache utilities on your project– How to hide the details
4 © 2008 CIBER, Inc. All rights reserved
Prerequisites
• Core Java SE• The right mindset
– Leverage existing utilities
5 © 2008 CIBER, Inc. All rights reserved
Session Non-Agenda
In this Session, we will not discuss:
• JavaEE• A full-blown application• Other cool Apache projects:
– Web Services (Axis 2)– CXF– XMLBeans– Geronimo– ServiceMix– ActiveMQ– Camel– Struts– Beehive
6 © 2008 CIBER, Inc. All rights reserved
Session Agenda
In this Session we will discuss:
• Commons Lang• Commons Configuration• Commons Logging and Log4J• POI• Commons Email• Velocity• HttpClient• Commons IO • Summary
7 © 2008 CIBER, Inc. All rights reserved
Session Roadmap
Where are we?
• Commons Lang• Commons Configuration• Commons Logging and Log4J• POI• Commons Email• Velocity• HttpClient• Commons IO • Summary
8 © 2008 CIBER, Inc. All rights reserved
Like Nails on a Blackboard …
if (myString == null || myString.length() == 0) { // Ugh!!
…
}
// OR only slightly better.
public class MyUtils {
…
public static boolean isNullOrEmpty(String stringToCheck) {
boolean retValue = false;
if (stringToCheck == null) {
retValue = true;
} else if (stringToCheck.length() == 0) {
retValue = true;
}
return retVal;
}
9 © 2008 CIBER, Inc. All rights reserved
Commons Lang Overview
• Enhanced methods and classes for core Java SE (java.lang)– http://commons.apache.org/lang
• Includes String, numerical, date/time methods• Useful: StopWatch (simple timing test)• My favorite – StringUtils:
– isBlank()– isEmpty()– isNotBlank()– isNotEmpty()
10 © 2008 CIBER, Inc. All rights reserved
With StringUtils
// Usage
if (StringUtils.isEmpty(myString)) {
…
}
if (StringUtils.isBlank(myString)) {
…
}
11 © 2008 CIBER, Inc. All rights reserved
Session Roadmap
Where are we?
• Commons Lang• Commons Configuration• Commons Logging and Log4J• POI• Commons Email• Velocity• HttpClient• Commons IO • Summary
12 © 2008 CIBER, Inc. All rights reserved
Getting Properties – What we want
String emailTo = MyPropertyUtil.getProperty(EMAIL_TO);
13 © 2008 CIBER, Inc. All rights reserved
Rolling Your Own Properties
public class MyPropertyUtil { private static final String MY_PROPS_FILE_NAME = “…”; // Use –D to set this at startup.
…
public static String getProperty(String key) throws MyPropertyUtilException { Properties props = null; String value = “”, propsFileName = System.getProperty(MY_PROPS_FILE_NAME);
if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(propsFileName) { try { // FIXMEE: Move Props File Name & Properties Load to static initializer.
// The Thread Context ClassLoader is the ClassLoader used by the creator // of the Thread that runs your code. By using the Thread Context ClassLoader, // we’re guaranteed to load the resource (class or property file) as long as // it's on the application's CLASSPATH.
ClassLoader myClassLoader = Thread.currentThread().getContextClassLoader(); URL myUrl = myClassLoader.getResource(name); props.load(url.openStream());
value = props.getProperty(key); } catch (Throwable th) { … } }
return value; }
14 © 2008 CIBER, Inc. All rights reserved
Commons Configuration Overview
• A clean way to configure your application– http://commons.apache.org/configuration
• It loads the configuration data for you• Configuration/Factory (main class) can work
with:– Properties files– XML files– JNDI– JDBC DataSource– System Properties (JVM)– .INI files (Windows)
15 © 2008 CIBER, Inc. All rights reserved
Commons Configuration Overview … Cont’d
• It can handle hierarchical data• It can combine multiple data sources
(composite):
CompositeConfiguration config = new CompositeConfiguration(); config.addConfiguration(new SystemConfiguration()); config.addConfiguration(new
PropertiesConfiguration("application.properties"));
16 © 2008 CIBER, Inc. All rights reserved
Properties with Commons Configuration
public class MyPropertyUtil { private static final String MY_PROPS_FILE_NAME = “…”; // Use –D to set this at startup.
…
public static String getProperty(String key) throws MyPropertyUtilException { Properties props = null; String value = “”, propsFileName = System.getProperty(MY_PROPS_FILE_NAME);
if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(propsFileName) { try { // FIXMEE: Move Props File Name & Constructor call to static initializer. Configuration config = new PropertiesConfiguration(propsFileName);
value = props.getString(key); } catch (Throwable th) { … } }
return value; }}
17 © 2008 CIBER, Inc. All rights reserved
Session Roadmap
Where are we?
• Commons Lang• Commons Configuration• Commons Logging and Log4J• POI• Commons Email• Velocity• HttpClient• Commons IO • Summary
18 © 2008 CIBER, Inc. All rights reserved
Session Roadmap
Where are we?
• Commons Lang• Commons Configuration• Commons Logging and Log4J• POI• Commons Email• Velocity• HttpClient• Commons IO • Summary
19 © 2008 CIBER, Inc. All rights reserved
POI Overview
• API to access MS file formats– Word– PowerPoint– Outlook– Visio– Publisher– Excel (HSSF)– http://poi.apache.org
20 © 2008 CIBER, Inc. All rights reserved
Generate an Excel File with POI
private static void populateExcelWorksheet(Collection rows, FileOutputStream fileOut) { try { if (rows.size() > 0) { HSSFWorkbook workBook = new HSSFWorkbook(); HSSFSheet workSheet = workBook.createSheet(); //Create new workSheet Iterator rowDataIterator = rows.iterator(); int rowNum = 0, maxColumnSize = 0;
while (rowDataIterator.hasNext()) { LinkedList rowStringsList = (LinkedList) rowDataIterator.next(); if (rowStringsList.size() > 0) { HSSFRow row = workSheet.createRow(rowNum); // Create header ONLY once if (rowNum == 0) { maxColumnSize = ExcelUtil.createColumnHeaders(rowStringsList, workBook, row); } else { maxColumnSize = ExcelUtil.fillRowCellValue(rowStringsList, workBook, row); } rowNum++; } }
21 © 2008 CIBER, Inc. All rights reserved
Generate an Excel File with POI … Cont’d
workBook.write(fileOut);
}
}
catch (IOException e) {
...
}
}
22 © 2008 CIBER, Inc. All rights reserved
Generate an Excel File with POI … Cont’d
private static short createColumnHeaders(LinkedList stringList, HSSFWorkbook workBook, HSSFRow row) { short columnNum = 0; Iterator iter = stringList.iterator(); while (iter.hasNext()) { String value = (String) iter.next();
// Create a new font and alter it. HSSFFont font = workBook.createFont(); //Customize font customizeExcelFont(font); // Fonts are set into a style so create a new one to use. HSSFCellStyle style = workBook.createCellStyle(); style.setFont(font);
HSSFCell cell = null;
cell = row.createCell(columnNum); cell.setCellStyle(style); cell.setCellValue(value); columnNum++; } return columnNum; }
23 © 2008 CIBER, Inc. All rights reserved
Generate an Excel File with POI … Cont’d
private static short fillRowCellValue(LinkedList stringList, HSSFWorkbook workBook, HSSFRow row) { short columnNum = 0; Iterator iter = stringList.iterator(); while (iter.hasNext()) { String value = (String) iter.next(); HSSFCellStyle style = workBook.createCellStyle(); HSSFCell cell = null; // Set background color with light "foreground" // foreground being the filled, not the font color. style.setFillForegroundColor(HSSFColor.LIGHT_GREEN.index); style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cell = row.createCell(columnNum); cell.setCellStyle(style); cell.setCellValue(value); columnNum++; } return columnNum; }
24 © 2008 CIBER, Inc. All rights reserved
Session Roadmap
Where are we?
• Commons Lang• Commons Configuration• Commons Logging and Log4J• POI• Commons Email• Velocity• HttpClient• Commons IO • Summary
25 © 2008 CIBER, Inc. All rights reserved
Commons Email Overview
• Simple API for sending email– http://commons.apache.org/email
• Based on JavaMail API (but easier to use)• Key Areas:
– Text– HTML– Attachments
26 © 2008 CIBER, Inc. All rights reserved
Using JavaMail
public void send(MyEmailParams emailParams) throws EmailException { // Send Text try { Session session = getDefaultSession(); InternetAddress[] recipientsArr = (InternetAddress[]) emailParams.getRecipients().toArray(new InternetAddress[0]);
MimeMessage msg = new MimeMessage(session); msg.setFrom(emailParams.getSender());
msg.setRecipients(Message.RecipientType.TO, recipientsArr); if (!emailParams.getCcRecipients.isEmpty(){ InternetAddress[] ccRecipientsArr = (InternetAddress[])
emailParams.getCcRecipients().toArray(newInternetAddress[0]); msg.setRecipients(Message.RecipientType.CC, ccRecipientsArr); }
27 © 2008 CIBER, Inc. All rights reserved
Using JavaMail … Cont’d
msg.setSubject(emailParams.getSubject()); msg.setText(emailParams.getBody()); Transport.send(msg); // Send message } catch (MessagingException me) { … } }
private Session getDefaultSession() throws EmailException { Properties props = new Properties(); String mailSmtpHost = MyPropertyUtil.getProperty(MAIL_SMTP_HOST), mailSmtpPort = MyPropertyUtil.getProperty(MAIL_SMTP_PORT), mailDebug = MyPropertyUtil.getProperty(MAIL_DEBUG, FALSE);
props.setProperty(MAIL_TRANSPORT_PROTOCOL, SMTP); props.setProperty(MAIL_SMTP_HOST, mailSmtpPort); props.setProperty(MAIL_SMTP_HOST, mailSmtpHost); props.setProperty(MAIL_DEBUG, mailDebug);
Session session = Session.getDefaultInstance(props);
return session; }
28 © 2008 CIBER, Inc. All rights reserved
Using Commons Email
public static void sendSimpleEmail(EmailParams emailParams) throws MyEmailUtilException { // Send text.
try { SimpleEmail email = new SimpleEmail(); String hostName = MyPropertyUtil.getProperty(MY_SMTP_SERVER); Iterator toAddrIter = emailParams.getToRecipients().iterator(), ccAddrIter = emailParams.getCcRecipients().iterator(); email.setHostName(hostName); email.setFrom(emailParams.getFromEmailAddr(), emailParams.getFromName()); while (toAddrIter.hasNext()) { email.addTo((String) toAddrIter.next()); } while (ccAddrIter.hasNext()) { email.addCc((String) ccAddrIter.next()); }
email.setSubject(emailParams.getSubject()); email.setMsg(emailParams.getMessage()); email.send(); } catch (EmailException e) { … } }
29 © 2008 CIBER, Inc. All rights reserved
Session Roadmap
Where are we?
• Commons Lang• Commons Configuration• Commons Logging and Log4J• POI• Commons Email• Velocity• HttpClient• Commons IO • Summary
30 © 2008 CIBER, Inc. All rights reserved
Velocity Overview
• Templating Engine– http://velocity.apache.org
• Other good tools exist:– FreeMarker – http://freemarker.sourceforge.net/
31 © 2008 CIBER, Inc. All rights reserved
Using the Velocity API
VelocityEngine velocityEngine = new VelocityEngine();Properties props = new Properties();Template template = null;VelocityContext velocityContext = new VelocityContext(); props.setProperty(VelocityEngine.RESOURCE_LOADER, "classpath");props.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER + ".class", ClasspathResourceLoader.class.getName());
velocityEngine.init(props);
try { StringWriter writer = new StringWriter(); template = velocityEngine.getTemplate(MY_TEMPLATE);
velocityContext.put(RECIPIENT_NAME, recipientName); velocityContext.put(POLICY_NUMBER, policyNumber); velocityContext.put(REFUND_AMOUNT, refundAmount);
template.merge(velocityContext, writer);} catch (…) { …}
32 © 2008 CIBER, Inc. All rights reserved
Velocity Template
<HTML><BODY> <p> Dear $recipientName, Due to your safe driving record, we are refunding $refundAmount on
your auto policy ($policyNumber). </p></BODY></HTML>
33 © 2008 CIBER, Inc. All rights reserved
Session Roadmap
Where are we?
• Commons Lang• Commons Configuration• Commons Logging and Log4J• POI• Commons Email• Velocity• HttpClient• Commons IO • Summary
34 © 2008 CIBER, Inc. All rights reserved
Commons HttpClient Overview
• API to help develop an HTTP Client– GET / POST– Authentication– Redirect– Proxy– Encodings– Cookies
• In its final release (3.x)– http://hc.apache.org/httpclient-3.x/index.html
• To be replaced by HttpComponents:– http://hc.apache.org– Still in Beta– “Not yet, grasshopper”
35 © 2008 CIBER, Inc. All rights reserved
HttpClient Example
public class MyHttpClient {… public static String sendPostRequest(MyRequestDto myRequestDto) throws MyHttpClientException {
String responseString = null; PostMethod httpPost = null; HttpClient httpClient = new HttpClient(); MyHttpClient.setupProxy(httpClient); try { // Create and send the HTTP Request. httpPost = MyHttpClient.setupHttpPostRequest(myRequestDto); httpClient.executeMethod(httpPost);
// Get the HTTP Status. if (httpPost.getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY) { MyHttpClient.handleRedirect(httpClient, httpPost); } //Get HTTP response. responseString = MyHttpClient.getHttpResponse(httpPost); …
36 © 2008 CIBER, Inc. All rights reserved
HttpClient Example … Cont’d
} catch (HttpException he) { … } catch (IOException ioe) { … } finally { httpPost.releaseConnection(); } return responseString; }
private static void setupProxy(HttpClient httpClient) { // Tunnel through a proxy. String useProxy = MyPropertyUtil.getProperty(USE_PROXY); if (StringUtils.isNotBlank(useProxy) && useProxy.equalsIgnoreCase(YES)) { String proxyHost = MyPropertyUtil.getProperty(MY_PROXY_HOST), proxyPort = MyPropertyUtil.getProperty(MY_PROXY_PORT), proxyRealm = MyPropertyUtil.getProperty(MY_PROXY_REALM), proxyUser = MyPropertyUtil.getProperty(MY_PROXY_USER), proxyPassword = MyPropertyUtil.getProperty(MY_PROXY_PASSWORD);
httpClient.getHostConfiguration().setProxy(proxyHost, Integer.parseInt(proxyPort));
httpClient.getState().setProxyCredentials(proxyRealm, proxyHost, new UsernamePasswordCredentials(proxyUser, proxyPassword));
} }
37 © 2008 CIBER, Inc. All rights reserved
HttpClient Example … Cont’d
private static PostMethod setupHttpPostRequest(MyRequestDto myRequestDto) { String myUrl = MyPropertyUtil.getProperty(ConfigConstants.CONFIG_MY_URL); PostMethod httpPost = new PostMethod(myUrl); // Populate HTTP Post Parameters. httpPost.addParameter(REDIR_KEY, REDIR_VALUE); httpPost.addParameter(FIRST_NAME_KEY, myRequestDto.getFirstName()); …
return httpPost; }
private static void handleRedirect(HttpClient httpclient, PostMethod httpPost) throws MyHttpClientException { try { Header locationHeader = httpPost.getResponseHeader(HTTP_RESPONSE_LOCATION_HEADER);
if locationHeader != null) { String redirectLocation = locationHeader.getValue(); httpPost.setURI(redirectLocation); httpClient.executeMethod(httpPost); } } catch (URIException ue) { … } // 2 others – HttpException, IOException }
38 © 2008 CIBER, Inc. All rights reserved
HttpClient Example … Cont’d
private static String getHttpResponse(PostMethod httpPost) throws MyHttpClientException { String responseString = null; InputStream is = null;
try { is = httpPost.getResonseBodyAsStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); StringBuffer responseBuffer = new StringBuffer(); String line = null; boolean done = false;
while (!done) { line = br.readLine(); done = (line == null); if (!done) { responseBuffer.append(line); } }
responseString – responseBuffer.toString().trim(); } catch (IOException ioe) { …
39 © 2008 CIBER, Inc. All rights reserved
HttpClient Example … Cont’d
} finally {
if (is != null) {
try {
is.close();
} catch (…) {
…
}
}
}
return responseString;
}
}
40 © 2008 CIBER, Inc. All rights reserved
Session Roadmap
Where are we?
• Commons Lang• Commons Configuration• Commons Logging and Log4J• POI• Commons Email• Velocity• HttpClient• Commons IO • Summary
41 © 2008 CIBER, Inc. All rights reserved
Commons IO Overview
• API to simplify IO processing– http://commons.apache.org/io
• Key Areas– Utility classes – Perform common tasks– Filters – File filter implementations– Comparators – For comparing lists of files– Streams – Stream, Reader and Writer
implementations
• My Favorite – IOUtils
42 © 2008 CIBER, Inc. All rights reserved
Stream I/O without Commons IO
private static String getHttpResponse(PostMethod httpPost) throws MyHttpClientException { String responseString = null; InputStream is = null;
try { is = httpPost.getResonseBodyAsStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); StringBuffer responseBuffer = new StringBuffer(); String line = null; boolean done = false;
while (!done) { line = br.readLine(); done = (line == null); if (!done) { responseBuffer.append(line); } }
responseString – responseBuffer.toString().trim(); } catch (IOException ioe) { …
43 © 2008 CIBER, Inc. All rights reserved
Stream I/O without Commons IO … Cont’d
} finally {
if (is != null) {
try {
is.close();
} catch (…) {
…
}
}
}
return responseString;
}
}
44 © 2008 CIBER, Inc. All rights reserved
Stream I/O with Commons IO
private static String getHttpResponse(PostMethod httpPost)
throws MyHttpClientException {
String responseString = null;
InputStream is = null;
try {
is = httpPost.getResonseBodyAsStream();
responseString = IOUtils.toString(is);
} catch (IOExeception ioe) {
…
} finally {
IOUtils.closeQuietly(is);
}
return responseString;
}
45 © 2008 CIBER, Inc. All rights reserved
Session Roadmap
Where are we?
• Commons Lang• Commons Configuration• Commons Logging and Log4J• POI• Commons Email• Velocity• HttpClient• Commons IO • Summary
– Conclusions– Questions– Resources
46 © 2008 CIBER, Inc. All rights reserved
Conclusions
• Apache has a wealth of useful APIs• SourceForge (and others) also have great APIs• Use thin wrappers to hide the details• Research Open Source before coding
– Don’t re-invent the wheel– Google, anyone?
47 © 2008 CIBER, Inc. All rights reserved
Questions?
Tom Marrs
Principal Architect
48 © 2008 CIBER, Inc. All rights reserved
Resources
• Apache Main Page: http://www.apache.org• Apache Commons: http://commons.apache.org
– Lang: http://commons.apache.org/lang– Configuration: http://commons.apache.org/configuration– Logging: http://commons.apache.org/logging– Email: http://commons.apache.org/email– IO: http://commons.apache.org/io– HttpClient: http://hc.apache.org/httpclient-3.x/index.html
• Apache Log4J: http://logging.apache.org/log4j/1.2/index.html• Apache Velocity: http://velocity.apache.org• FreeMarket: http://freemarker.sourceforge.net• Apache POI: http://poi.apache.org• Apache HttpComponents: http://hc.apache.org