Labels

.net (1) *nix (1) administration (1) Android (2) Axis2 (2) best practice (5) big-data (1) business-analysis (1) code re-use (1) continuous-integration (1) Cordova-PhoneGap (1) database (2) defect (1) design (3) Eclipse (7) education (1) groovy (2) https (2) Hudson (4) Java (1) JAX-RS (2) Jersey (3) Jetty (1) localization (1) m2eclipse (2) MapForce (1) Maven (12) MySQL (1) Nexus (4) notes (4) OO (1) Oracle (4) performance (1) Perl (1) PL/SQL (1) podcast (1) PostgreSQL (1) requirement (1) scripting (1) serialization (1) shell (1) SoapUI (1) SQL (1) SSH (2) stored procedure (1) STS (2) Subclipse (1) Subversion (3) TOAD (3) Tomcat (4) UML (2) unit-testing (2) WAMP (1) WAS (3) Windows (3) WP8 (2) WTP (2) XML (4) XSLT (1)

Monday, December 26, 2011

Problems installing Groovy-Eclipse extension in SpringSource Tool Suite 2.7.1

Attempting to install the Groovy-Eclipse extension in STS 2.7.1, I received obscure error messages about a conflicting dependency with a Maven extension.  Using a new workspace did not fix the problem.  When trying with STS 2.8.1, I received a much better error message:  that I could not install since STS was in the C:\Program Files directory.  To verify this, I moved my STS program directory to the root of C: and tried to install the Groovy-Eclipse extension again:  No problems this time.

Comparing against some of my other computers with STS and the Groovy-Eclipse extension installed, it appears that the Groovy-Eclipse extension does not like the space character in C:\Program Files.


Thursday, December 1, 2011

Third-party JARs and Nexus

The Nexus documentation (start here and Uploading Artifacts) is quite good for what to do to deal with third-party JARs and basically JARs that don't reside in any repository out in the rest of the world (obsolete versions or proprietary).  However, if you aren't careful, the Nexus user interface can be misleading.  For the Artifact Upload interface, it can be easy to select the POM file and select the JAR artifact, but neglect to press the Add Artifact button.



Nexus will then simply upload the POM file but not the JAR file.  At this point, the clean-up of the mess begins.

Your Maven build will fail, not being able to locate the JAR file.  If you attempt to re-do the step, but this time, pressing the Add Artifact button, you will get the following error:

You need to clean up the repository of the Nexus server, which you can do by going to the Browse Storage tab > navigating to the appropriate section by GAV > right-click > Delete. 

 However, if you attempt another build, Maven will fail again.  If you look at the build log, you will see something like:
Failure to find ... in http://.../nexus/content/groups/public was cached in the local repository, resolution will not be reattempted until the update interval of nexus has elapsed or updates are forced

The next step is to go to the Local repository where the Maven build ran and clean it up.  Navigate in the file system by GAV and you will find files named similarly to:
some-artifact-0.1.jar.lastUpdated
some-artifact-0.1.pom.lastUpdated

Delete these, re-run the Maven build.  It should find your artifacts now.

Wednesday, November 30, 2011

Getting Groovy test cases to run with Maven

Groovy is excellent for writing test cases because of its brevity and meta-programming capabilities.  For example, a class that I was using to do integration testing called System.exit in its main method.  With Groovy I could re-define its main method so that I could continue running the rest of my test code:

        Launcher.metaClass.'static'.main = { String[] args ->
            delegate.programArguments = args
            delegate.init()
            delegate.run()

            // No more System.exit!
        }


However, to get Groovy test cases to run inside Maven (and outside of Eclipse) requires some tweaks.  First of all, you have to make Maven aware that there are Groovy test cases to execute, or else it won't even find them  The section "Configuring Maven2 to compile and run your Groovy tests" in the article Writing unit tests using Groovy is mostly correct but it is out-of-date.  If you use its Maven coordinates verbatim, you will have errors in your Maven output.

Error:  Execution default of goal org.codehaus.mojo.groovy:groovy-maven-plugin:1.0-beta-3:testCompile failed: An API incompatibility was encountered while executing org.codehaus.mojo.groovy:groovy-maven-plugin:1.0-beta-3:testCompile: java.lang.NoSuchMethodError: org.codehaus.plexus.PlexusContainer.hasChildContainer(Ljava/lang/String;)Z
This can be corrected by changing the coordinates of the Groovy Maven plugin to:              
<groupId>org.codehaus.mojo</groupId>
<artifactId>groovy-maven-plugin</artifactId>
<version>1.3</version>

Error:  Failed to execute goal org.codehaus.mojo:groovy-maven-plugin:1.3:testCompile ... Unknown type: METHOD_DEF
This can be caused by anonymous inner classes in the code.  Groovy for Java Programmers gives some suggestions for how to re-format your code so that Groovy can properly parse it and recognize an anonymous inner class definition, however these suggestions didn't work for me.  Anonymous inner class are a convenience so one can re-write the code to eliminate them.

Error:  initializationError(...): [Lorg/codehaus/groovy/runtime/callsite/CallSite;
You may only see one line in the Maven output which is not particularly helpful.  However, you can look at the detailed test output.  In Hudson, it would be at a location under HUDSON_HOME similar to jobs\<your job>\workspace\target\surefire-reports\  Looking here, you may see an error java.lang.NoClassDefFoundError: [Lorg/codehaus/groovy/runtime/callsite/CallSite;
To fix this, update your Groovy Maven run-time coordinates to:

<groupId>org.codehaus.groovy.maven.runtime</groupId>
<artifactId>gmaven-runtime-1.6</artifactId>
<version>1.0</version>
<scope>test</scope>

After all this, you should finally see your Groovy test executed in the Maven output.

Tuesday, November 29, 2011

Maven install:install-file output is misleading?

Using Apache Maven 3.0.3 (r1075438), Maven will report "BUILD SUCCESS" even when the file argument points to a non-existent file (e.g. mvn install:install-file -Dfile=C:\temp\jmockit.jar ...).  Naturally, this can lead to some confusion when your source code still refuses to compile.

Monday, November 14, 2011

XPath heaven and Namespace hell

XPath is fairly easy to learn by example (great examples here) but namespaces in the XML can be maddening when they cause data to be alluded.  Some things to check before you resort to using simple string matching or regular expressions to get to your XML data:
  • XPath expressions are case-sensitive
  • Indexing is 1-based rather than 0-based, e.g. /MSG.2[1] refers to the first element (not the second element)
  • Default namespaces (e.g. xmlns="urn:hl7-org:v3" vs. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance", the former having a default namespace) requires that you set up a prefix for the namespace if you want to write XPath expressions against the XML content.  Good article about default namespaces 
  • When writing XPath expressions where namespaces are involved, you need to prefix each element in the expression (with the appropriate namespace prefix).  E.g. /hl7v3:PRPM_IN301030CA/hl7v3:controlActEvent/hl7v3:effectiveTime is required, /hl7v3:PRPM_IN301030CA/controlActEvent/effectiveTime will not work (there is no inheritance down the branch)


Thursday, October 13, 2011

You Are not the User

Read Ask "What Would the User Do?" (You Are not the User) last week or so.  My thoughts on the article:
  • It is always better to have a prototype, on paper or a digital mockup, of the user interface so that a user can work through it, rather than a verbose "user interface requirements" document
  • As developers, although we usually are able to figure out new user interfaces we encounter, we often do the same things novice users do especially when things don't work as expected.  E.g. once we figure out a user interface, we may do the same steps all the time instead of looking for a short-cut.  And sometimes we stick with the same tools or older versions because we find it too much of a learning curve to try new ones

Monday, October 3, 2011

97 Things

Making time to read one article everyday from 97 Things Every Programmer Should Know (book format or online) and write about it the following day or soon after.  Advice I've read so far:
  • "Act with Prudence" - one way (not perfect) to keep track of technical debt is to use TODOs in the code.  The text associated with a TODO should be specific enough so that someone else reading it in the context of the code understands what still needs to be done.  
  • "Apply Functional Programming Principles" - (a) indeed, as the author Edward Garson states, mis-use of object-oriented programming creates bad designs.  In particular, IMO, the difference between using setters versus parameters to a method is not entirely clear.  The advent of Spring also has popularized the use of setters although Spring can just as easily work with constructors so that when an object is instantiated, its state is correct and it is ready to be used.  My rule of thumb is when in doubt, use parameters to a method to pass arguments, not with setters.  (b) As the author also states, test-driven design also helps to promote better design.  IMO it is because as you write automated test cases, you become a user of your API ("Eating your own dog food" principle), and you begin to understand what makes an API easier/cleaner to program against.  

Tuesday, August 16, 2011

PostgreSQL server starts up but then stops immediately

On Windows, starting through the Services window will indicate the above with a message similar to "The PostgreSQL Server 8.4 service on Local Computer started and then stopped.  Some services stop automatically if they have no work to do, for example, the Performance Logs and Alerts service".


Check the Event Viewer (shortcut:  Type "eventvwr" in Start > Run). In my situation, the data directory I specified at installation time appeared to not exist as indicated by the error message "FATAL:  data directory "XXXXXXXXXXXX" does not exist".  However it appears to be a permission problem, as the directory indeed existed. 
 
The easiest solution is to uninstall and reinstall and specify a directory that you know the postgres user ID will have no issues accessing (e.g. the default data directory suggested by the installer)

Tuesday, August 9, 2011

Maven project has errors in Eclipse (no changes were made)

Possible fixes:

  1. More common:  If Project > Build Automatically is checked off, do a Project > Clean on the problematic project.  Usually this fixes the issue.
  2. If compile errors persist, especially indicating dependencies that should be resolved by Maven, Project > Update All Maven Dependencies.  This may be needed if the local repository was moved; Eclipse may need to be refreshed of this.  
    • Speaking of which, after moving the Maven local repository, simply update the path in the settings.xml file in the .m2 directory in your home directory (e.g. C:\Documents and Settings\alan.leung\.m2 or ~/.m2 on *nix)

Tuesday, July 19, 2011

Configuration objects read from/saved to files

For Spring-enabled applications, Spring has a rich configuration scheme, and objects can be fully configured and wired together based on the directives specified.

Alternatively, one can consider defining the application configuration by code, serializing the configuration objects to file as a starting point, and then, as needed, editing the configuration in file format.  When the application starts up, it will read in the configuration, de-serialize it back into object form and the application can work with the configuration.

Not unexpectedly, Spring has a way to set up marshallers/unmarshallers for your application so that it is opaque to the application which XML serialization library it is using.  This makes it easy to swap out for a different library.  I tried three different libraries with Spring and these are my findings:

Library PROS CONS
JAXB "The standard for Java"?
  • Require jaxb.index file in package's folder
  • Need to annotate class with @XmlRootElement
  • Have to have no-arg constructors even if it is against design practices
  • Doesn't work with Interfaces and cannot de-serialize a class extending from an abstract class
Castor
Popular?
Serializes well but on deserializing, get an error of
org.springframework.oxm.castor.CastorUnmarshallingFailureException: Castor unmarshalling exception: The class for the root element 'anonymize-settings' could not be found.; nested exception is org.exolab.castor.xml.MarshalException: The class for the root element 'anonymize-settings' could not be found.

For whatever reason, Castor doesn't add the xsi:type attribute on the root element when it serializes. 
XStream
  • Actually works
  • Codebase doesn't have to change for XStream to work with it (no design compromises)
Not popular?  But the library is so simple to use, there is absolutely no learning curve so you don't have to devote a lot of time to it

Monday, April 25, 2011

Notes on early TSS.NET Unit Testing article

  • Article
  • "A test fixture is a class that contains a series of test methods ... This grouping is important for two main reasons: one, it creates a subset of tests that can be run as a group, separate from other groups of tests, and two, it provides a level of granularity for controlling the lifecycle and context of a test."
  • For database code, article suggests using stored procedures to initialize database for a unit test and calling these stored procedures in SetUp and TearDown.  Also, more specific stored procedures to create additional data for specific tests.  More ideas:  Get Test Infected with NUnit: Unit Test Your .NET Data Access Layer 
  • a mock object will have the same interface as the "real" object.  The implementation of the mock object should track usage, allowing you to determine if the right calls were made (by the tested code), and expose any methods/properties that test code might use to evaluate results.  Rather than implement yourself, can use a dynamic mock object library such as NMock
  • Nester helps verify code coverage by unit testing:  "involves modification of programs to see if existing tests can distinguish the original program from the modified program" (mutation testing)
  • So that test code doesn't force breaking encapsulation of the tested code, have tests reside in same assembly and namespace as code being tested.  Then non-public methods/properties that need to be accessed by test code can be marked with internal modifier

Friday, March 25, 2011

Unable to find resource 'xxxxxxxxxxxx:xxxxx:maven-plugin:x.x.x' in repository central

Although one may think to correct this by adding a <repository> specification in the POM file, a closer look at the error messages, including "A required plugin was not found: Plugin could not be found - check that the goal name is correct: Unable to download the artifact from any repository" may give another clue.  For plugins, a <pluginRepository> specification is required.

Tuesday, March 15, 2011

Deploy to own Maven repository using SSH

  • Maven command:  mvn deploy:deploy-file -DgroupId=<groupId> -DartifactId=<artifactId> -Dversion=<version> -Dpackaging=<e.g. jar or war, etc.> -Dfile=<path to file>-Durl=<e.g. scpexe://your hostname/full file system path to repo on server> -DrepositoryId=<id of repo in settings.xml>
  • References:  Deployment of artifacts in an external SSH command and Deploy Plugin

Requirements gathering/Analysis

Key challenges:
  • Tracking issues, decisions and rationale
  • Transform ambiguity to concrete rules/processes
  • Explaining process logic concisely
  • Closing any loop-holes in process
Tracking issues:

  • Email - organize by project, subject.  Use tags for content that falls into more than one folder
  • Spreadsheet or similar - columns:  Date issue raised, issue, issue ID, resolution, who is addressing, what is resolution pending on, related documents or emails
Explaining process:
  • use of flowcharts, sequence diagrams or swim lane diagrams.  Use case diagrams to summarize and group according to user role
  • number the steps so that they can be talked to and addition explanation can be associated with a given step

Friday, February 25, 2011

Shell scripting gotchas

  • If strange behavior is encountered running an existing (working) script, your default shell may differ.  At the top of the script, you may need to explicitly set your shell, e.g. change #!/bin/sh to #!/bin/bash
  • Whitespace is very important to the declaration of variables, that is:
  • numSections = 0;
    
    attempts to execute a command named numSections whereas
    numSections=0;
    
    declares a variable of name numSections 
See this page for updates to this blog post.

Friday, February 4, 2011

Executing Oracle stored procedure with TOAD

In this example, the stored procedure returns a ref_cursor based on some input parameters.  In a TOAD Editor window, have something like this: 

select MySchema.MyPackage.MyStoredProcedure('param1', 'param2') from dual

and click on .

You will get results as a 1 by 1 grid, a concatenation of all the results, created by TOAD.