Apache Utilities At Work V5

Preview:

DESCRIPTION

You're on another typical JavaEE-based project, and you find yourself writing the same old infrastructure code. Are you wondering if there's a quicker way to incorporate the basics such as configuration, logging, and email into your application? If so, then this presentation is for you. By using a number of Apache utilities fromCommons, Logging, and other areas, you can learn how to stop re-inventing the wheel.We'll start with a simple Struts 2 application and iteratively add the ability to:• Use Commons Lang for String and Date utilities.• Use Commons Property Configuration to setup and use application Properties.• Use Commons Logging and Log4J to log messages.• Generate Excel spreadsheets with POI.• Use Velocity Templates and Commons Email to format and send email messages.• Use HttpClient to invoke web apps with HTTP/S.• Use Commons IOUtils to simplify accessing web content.

Citation preview

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

thomasamarrs@comcast.net

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

Recommended