Friday, September 13, 2013

Migrating from Ant to Maven

Sample steps to migrate a java webapp from using Ant to Maven as the build tool.

Install maven


Learn about maven
Look up some maven tutorials and documentation e.g.


Reorganise source files
  • Create a skeleton maven directory structure for your code using an appropriate maven archetype command e.g run commands similar to the following on the command line.

For a war
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=com.mycompany -DartifactId=mywebapp


For a jar
mvn archetype:create -DgroupId=com.mycompany -DartifactId=myjar


  • Copy java source files directories from the ant project to the appropriate maven structure location e.g. C:\maven-migration\mywar\src\main\java\
  • Copy non-java files that are in the classes directory to the appropriate maven structure location e.g. C:\maven-migration\mywar\src\main\resources
  • Copy other web resources (everything else that is not within the classes directory) to the appropriate maven structure location e.g. C:\maven-migration\mywar\src\main\webapp
  • Delete the WEB-INF\lib directory under the maven webapp directory, if that was the location of libraries.


Create dependencies for libraries
  • From the ant project’s WEB-INF\lib directory, go through the libraries one at a time, determining if the library is used directly by your code. If so, add a dependency for the library to your maven project’s pom file. Use a maven central search website to determine dependency details like artefact id etc. e.g. http://www.maven-repository.com/. Mark or identify these as resolved e.g. on a piece of paper listing all the libraries.
  • Next, go through the remaining libraries and figure out which libraries are a dependency of one of the libraries already added. You may need to review the poms of the added libraries. You can see the library poms from the maven central search website. An IDE can also help to identify indirect dependencies e.g. Eclipse has a Dependency Hierarchy feature that shows these. Mark the indirect dependencies you’ve identified as resolved.
  • From the remaining libraries, identify those which are not used by your code directly but are required at runtime or for testing. Add these dependencies to your maven project pom with a runtime or test scope as appropriate. Mark these dependencies and the indirect dependencies that they bring, as resolved.
  • You’ll likely be left with non-maven libraries that aren’t built using maven or which aren’t available on a public maven repository. You’ll need to download packages for these libraries and see if they contain an indication of the libraries that they depend on. You’ll then need to create a pom for these libraries and deploy them to some maven repository e.g. an in-project one, see https://devcenter.heroku.com/articles/local-maven-dependencies
  • Once you have all the libraries matched, refine the dependencies in your pom e.g. to define exclusions for indirect dependencies that you don’t use. You can also override versions of libraries included.
  • Define other aspects of the pom similar to what is found in your ant project’s build.xml file e.g. configuration of the maven-compiler-plugin to generate java 1.6 compatible classes







Thursday, September 12, 2013

Installing Sonatype Nexus Open Source

Sonatype Nexus Open Source (Nexus OSS) is a repository manager for maven repositories.

Prerequisites
Maven

Versions used
Nexus OSS 2.0.5-04
Maven 3.0.4

Steps
  • Download the nexus oss zip package from http://sonatype.org/nexus
  • Extract the zip file to a folder created for nexus e.g. C:\nexus
  • Installation is complete

Running nexus
  • Open a command prompt window and navigate to the the NEXUS_HOME\bin directory e.g. C:\nexus\nexus-2.0.5-04\bin\
  • Run the command nexus.bat console
  • Open a browser and navigate to localhost:8081/nexus. The nexus interface should be displayed.
  • To install nexus as a service, run the command nexus.bat install
  • The nexus service name is nexus-webapp. Now you can start/stop nexus like any other service e.g. using the command net start nexus-webapp. To uninstall the service, run the command nexus.bat uninstall
  • On the nexus home page, click on the Log In link. The default login username/password is admin/admin123. There is also a default deployment user with username/password deployment/deployment123. You can change any of these passwords by expanding the Security section on the left hand pane, selecting the Users option, right-click on the desired user and selecting the Set Password context menu.

Configuring maven to use nexus
  • You can set maven to look for artefacts from nexus instead of directly from the internet e.g. the maven central repository. A Nexus proxy repository acts as a local cache for a remote repository.
  • Create or edit the USER_HOME_DIR\.m2\settings.xml file e.g. C:\Users\ANDY\.m2\settings.xml, to configure nexus as the mirror for all repositories e.g.

  
    
      
      nexus
      external:*
      http://localhost:8081/nexus/content/groups/public
    
  
  
    
      nexus 
      
      
      
        
          central
          http://central
          true
          true
        
      
     
        
          central
          http://central
          true
          true
        
      
    
  
  
    
    nexus
  

Installing Maven 3.0.4

Apache Maven is an open source build automation tool for java projects.

Prerequisites
JDK

Versions used
Maven 3.0.4
JDK 1.6.0_39

Steps

  • Download the maven binary zip package from http://maven.apache.org
  • Extract the zip file to some folder e.g. C:\. A folder structure like C:\apache-maven-3.0.4 will be created
  • Add the environment variable MAVEN_HOME with the value of the maven home directory e.g. C:\apache-maven-3.0.4\
  • Add the %MAVEN_HOME%\bin location to the PATH environment variable
  • The setup is complete. Open a command prompt window and type the command mvn -version to confirm.
  • The local maven repository is located in <USER_HOME_DIR>\.m2\repository e.g. C:\Users\TOM\.m2\repository
  • Note that maven requires internet access to download dependencies and may do so from time to time depending on the command and project given. Once a dependency is downloaded once, it is put in the local repository and will not be downloaded again.

Thursday, October 25, 2012

Moving from svn to hg on Sourceforge

The following details steps one can take to change the version control system for their Sourceforge project from subversion to mercurial. The steps are mainly based on http://www.alteridem.net/2010/07/28/migrating-from-subversion-to-mercurial/  

Prerequisites
Tortoisesvn
TortoiseHg  

Versions used
Tortoisesvn 1.7.1
TortoiseHg 2.5.1

Steps
  • Create a directory to hold a local copy of your svn repository e.g. c:\svnrepo Create the local svn repository in the newly created directory e.g
svnadmin create c:\svnrepo
  • This process will create a number of directories and files in the c:\svnrepo directory
  • Create an empty file named pre-revprop-change.bat in the c:\svnrepo\hooks directory
  • Initialize the local svn repository for syncing with the remote repository e.g.
svnsync init file:///c:/svnrepo http://svn.code.sf.net/p/myproject/code
  • Sync the repositories
svnsync sync file:///c:/svnrepo
  • This will copy/download files from the remote repository to the local one so it may take some time and bandwidth depending on the size of the remote repository
  • Make some configurations to TortoiseHg. Open windows explorer, right click on any directory and select the TortoiseHg > Global Settings menu. Select Commit in the left hand pane and enter a username. The conventional format is firstname lastname <email>. Select the Extensions option on the left hand pane and tick the convert extension. Click on OK to save these settings 
  • Create a directory to hold a local copy of your hg repository e.g. c:\hgrepo 
  • Create the local hg repository in the newly created directory e.g
hg init c:\hgrepo
  • Convert the local svn repo to hg, putting the results in the local hg repository
hg convert c:/svnrepo c:/hgrepo
  • Push your local hg repository to the remote hg repository
cd c:\hgrepo
hg push ssh://myusername@hg.code.sf.net/p/myproject/mymountpoint
  • This will upload the project files to the remote repository and may take a considerable amount of time depending on the size of the repository and upload speeds.

Java: Split string by newline

String lines[] = currentValue.split("\\r?\\n");

Sunday, February 12, 2012

Tools

Free and Open Source Tools.

Function Tools
VB.NET IDE Visual Basic Express Edition

SharpDevelop
Reports for VB.NET applications SQL Server Express with Advanced Services (to design report) + Report Viewer redistributable/control (to display report in .NET application)
Report designer and runtime for VB6 applications Report Manager Designer and ActiveX (http://reportman.sourceforge.net/)
Project management ProjectLibre
Dictionary [offline] Wordweb
Office automation LibreOffice
Setup authoring NSIS with HM NIS Edit for a GUI

Advanced installer free edition

Excelsior Installer

WiX
.NET Obfuscator Eazfuscator.NET
SQLite GUI SQLiteStudio

Sqliteman

SQLite2009 Pro Enterprise Manager
CD Writing CDBurnerXP
Download manager/accelerator DownThemAll firefox add-on
Firewall Comodo Internet Security
Spyware remover Spybot search & destroy
Web server Apache HTTP server
Database PostgreSQL

SQL Server Express edition

MySQL

CUBRID (Web application needs)

HSQLDB (Embedded + Java needs)

SQLite (Embedded needs)
MySQL GUI HeidiSQL

Toad for MySQL Freeware

MySQL Workbench

Adminer

PhpMyAdmin
Disk space viewer WizTree

TreeSize Free
Image resizing Picture Resize Genius

Wiseval Photophant
Telnet client PuTTY
Music player Winamp free edition
Text editor Notepad++
Disk Encryption [On-The-Fly Encryption] FreeOTFE

FreeOTFE Explorer

TrueCrypt
Virtualization VirtualBox
CD Drive emulator VirtualCloneDrive
Startup programs manager Autoruns
Convert/Save documents or web pages as PDF PDF Creator
Asymmetric encryption GPG

Gpg4win
File comparison Winmerge
File compression 7-zip
FTP Client Filezilla
FTP Server Filezilla server
Screen capture Screenhunter free
Perl interpreter ActivePerl
MD5/SHA-1 hash verifier HashTab

DigestIT 2004
Email server hMailServer
Password storage KeePass Password Safe
Website copier WinHTTrack
Software licencing ActiveLock (http://www.activelocksoftware.com/)
Regex editor Rad regex designer (http://www.radsoftware.com.au/regexdesigner/)
Password generator PasswordGen (http://www.sdean12.org/PasswordGen.htm)

PC tools password utilities (http://www.pctools.com/guides/password/)

GRC ultra high security password generator (https://www.grc.com/passwords.htm)

Xyzzy
Email client Thunderbird

Windows live mail
XML Editor foxe - FirstObject Xml Editor (http://www.firstobject.com/dn_editor.htm)

Notepad++
Universal database GUI. Use to manage any DMBS. Squirrel SQL client
Enterprise reporting [report deployment, report distribution, web-based reporting, business intelligence] ART (http://art.sourceforge.net)

Pentaho BI suite Community Edition

Jaspersoft BI suite Community Edition
Bug tracking MantisBT
Convert music/video files to different formats VLC media player
Java decompiler JD-GUI
ETL Pentaho Data Integration [Kettle]
OLAP cube viewer and MDX generator Rex (http://sourceforge.net/projects/whex)

Web based IMAP client [webmail, webmail client] SquirrelMail

Roundcube

AtMail open

Horde IMP
LDAP server Apache Directory Server - ApacheDS
LDAP browser [ldap client] Apache Directory Studio
Difference in database schemas SQL Power Architect Community Edition (http://www.sqlpower.ca/page/products OR http://code.google.com/p/power-architect/)

MySQLDiff (http://www.mysqldiff.org/)
Data generator Spawner (http://sourceforge.net/projects/spawner/)

Dategenerator (http://www.generatedata.com)
Data warehousing database Infinidb Community Edition
Sms library Gsmcomm

SMSLib
.NET library to read or write excel files without having MS office installed NPOI (http://npoi.codeplex.com/)
Generate .NET program documentation from xml comments ImmDoc.Net (http://immdocnet.codeplex.com/)
Profiler for SQL Server Express editions AnjLab sql profiler (http://sites.google.com/site/sqlprofiler/)
Review resource usage by processes Process Explorer (http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx)
Manage ssl certificates available to java Portecle
Reminder to take breaks Workrave

FadeTop
Document Management System OpenKM
Merge text files TXTcollector (http://bluefive.pair.com/txtcollector.htm)
Software testing management TestLink
Determine who is using which port TCPView
Manage frequent ip address changes NetSetMan
Unlock files that can’t be deleted because they are locked by some process Unlocker

Using JasperReports

JasperReports is a java report library that can be used to add reporting capability to an application.

Using JasperReports in a Java EE application


Prerequisistes

JRE
Servlet engine
RDBMS + JDBC driver for a database
Apache Ant

Versions used
JRE 1.6.0_21
Apache Tomcat 6.0.29
MySQL 5.1.50
MySQL connector/J 5.1.13
JasperReports 3.7.0
Apache Ant 1.8.1

Steps
  • Download the jasperreports project zip file from sourceforge, http://sourceforge.net/projects/jasperreports/
  • Extract the zip file to a temporary location e.g. C:\temp
  • Open a command prompt
  • Navigate to c:\temp\jasperreports-3.7.0-project\jasperreports-3.7.0\demo\samples\webapp
  • Type the command ant javac [the path to the ant bin folder needs to be in the system path]
  • Create a folder in the tomcat webapps directory e.g. jasper
  • Copy the contents of the webapp directory to the webapps\jasper directory. This sample web application can serve as a guide on how to integrate jasperreports into your own web application.


Using in a custom application
  • Copy the following files from the webapps\jasper\web-inf\lib\ directory to your application's web-inf\lib directory. commons-beanutils-1.8.0.jar, commons-collections-2.1.1.jar, commons-digester-1.7.jar, commons-logging-1.0.4.jar, jasperreports-3.7.0.jar, iText-2.1.0.jar (for pdf export), poi-3.2-FINAL-20081019.jar (for xls export). For generating charts you'll need jfreechart and jcommon.


Generating a report
import net.sf.jasperreports.engine.*; //for main jasper objects
import net.sf.jasperreports.engine.export.*; //for exporters

JasperReport jasperReport;
JasperPrint jasperPrint;
JRResultSetDataSource ds;

ServletContext context = this.getServletConfig().getServletContext();  
String fileBase="report1";

String fileName=context.getRealPath("/reports/"+fileBase+".jasper");

File reportFile = new File(context.getRealPath("/reports/"+fileBase+".jasper"));
if (!reportFile.exists()) {
//compile file
fileName=JasperCompileManager.compileReportToFile(context.getRealPath("/reports/"+fileBase+".jrxml"));   
}

//rs is a resultset generated by your application. You can also pass a connection instead of a resultset if you want to use the query as it is in the repoort template    
ds = new JRResultSetDataSource(rs);

HashMap parameters=new HashMap(); //use a map to pass report parameters  
jasperPrint = JasperFillManager.fillReport(fileName, parameters,ds);

//export to pdf   
JasperExportManager.exportReportToPdfFile(jasperPrint,fullFileName);

//export to html
JRXhtmlExporter exporter = new JRXhtmlExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, fullFileName);
exporter.exportReport();

//export to xls
JRXlsExporter exporter = new JRXlsExporter();    
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, fullFileName);
exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
exporter.exportReport();


Passing parameters
  • If passing parameters, the parameter value data type in the parameters map must match the data type of the parameter as declared in the report template.

Example template query using a single value parameter
select * from customers where customer_id = $P{customer_id_param}
Example template query using a multi value parameter
select * from products where $X{IN, category, categories_param}

select * from products where $X{NOTIN, category, categories_param}
For multi value parameters, define the parameter class in the jrxml file as java.util.List. Pass values using an array list e.g
List categories = new ArrayList();
categories.add("Laptop");
categories.add("PC");
categories.add("Printer");
parameters.put("categories_param", categories);

Using virtualizers
  • A virtualizer can be used to enable large reports to be generated successfully, without resulting in out of memory errors. Using a virtualizer doesn't guarantee filling of arbitrarily large reports. Heap memory is still needed but memory requirements are reduced.
  • Also, once a report is filled, whether it can be exported successfully depends on the export format and library. e.g. Filling may be successful, generating a jasper print object but exporting to excel may fail because poi puts all the data in memory before generating the final file. Adding available heap memory may help to have a successful export.
  • If a report contains images, this may also be a cause of out of memory errors. In such a case, the virtualizer doesn't help until you set the image's properties "isUsingCache" to false and "isLazy" to true in the report template.
import net.sf.jasperreports.engine.fill.*; //for virtualizers
import net.sf.jasperreports.engine.util.*; //for jrswapfile

//use virtualizer if required
JRAbstractLRUVirtualizer virtualizer=null;

if(!props.getProperty(VIRTUALIZER).equals("none")){
if(props.getProperty(VIRTUALIZER).equals("file")){
int maxSize=Integer.parseInt(props.getProperty(FILE_MAX_SIZE));
virtualizer=new JRFileVirtualizer(maxSize,System.getProperty("java.io.tmpdir"));
params.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
} else if(props.getProperty(VIRTUALIZER).equals("gzip")){
int maxSize=Integer.parseInt(props.getProperty(GZIP_MAX_SIZE));
virtualizer=new JRGzipVirtualizer(maxSize);
params.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
} else {
//use swap virtualizer by default
int maxSize=Integer.parseInt(props.getProperty(SWAP_MAX_SIZE));
int blockSize=Integer.parseInt(props.getProperty(SWAP_BLOCK_SIZE));
int minGrowCount=Integer.parseInt(props.getProperty(SWAP_MIN_GROW_COUNT));

JRSwapFile swapFile=new JRSwapFile(System.getProperty("java.io.tmpdir"),blockSize,minGrowCount);
virtualizer=new JRSwapFileVirtualizer(maxSize,swapFile);
params.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
}
}

//fill report with data
JasperPrint jasperPrint;
if(rs==null){
//use template query
connQuery = ArtDBCP.getConnection(datasourceId);      
jasperPrint = JasperFillManager.fillReport(jasperFileName, params,connQuery);
} else {
//use recordset based on art query 
JRResultSetDataSource ds;
ds = new JRResultSetDataSource(rs);
jasperPrint = JasperFillManager.fillReport(jasperFileName, params,ds);
}

//set virtualizer read only to optimize performance. must be set after print object has been generated
if(virtualizer!=null){
virtualizer.setReadOnly(true);
}

//export report
...

//clean up
if(virtualizer!=null){
virtualizer.cleanup();
}

Notes
  • If the resultset is null, by default, the generated report will consist of a completely blank page. To display other report sections and only have the data section blank, if using iReport, change the report properties "when no data" option to "all sections, no detail".
  • If the report contains images, the image files should be located in the same directory as the jrxml file
  • If a parameter is used in a query and is not provided, it will be ignored, as if the condition didn't exist