Tuesday, August 22, 2017

Why is Spring @Value not working to read my parameter and default value?

In my small Spring project, i have a value that i may need to change of on of my parameters.  The simple solution would be
@Value("${myParam:defaultVal")
private String myParam;
Yet it was not working and the value was coming out as "$myparam:defaultVal".

What's the issue?
Eventually i stumbled upon the issue via this spring issue. I also saw it addressed here although there is a mistake as it is not sufficient to use util:properties as explained here. So, to make this work if you are using XML just add this in:

<context:property-placeholder location="classpath:/myfile.properties"/>

Now hopefully this wont happen again to me...

Tuesday, June 13, 2017

Using Gradle for a mixed groovy and java project and creating a distribution zip

Yes, I still use Groovy upon occasion. Groovy still is more readable and elegant in a lot of instances even than Java 8.

Ok but let's say i am writing both java and groovy in the project
In order to have this work, you need to configure your Gradle project with the following small changes so that you can make it compile the mixed code.

You need to make all the code compile as Groovy code (even the Java code).
So, add the following lines to your project:

sourceSets.main.java.srcDirs = []
sourceSets.main.groovy.srcDirs += ["src/main/java"]

This makes all your java code compile with the Groovy compiler to prevent dependency issues between the Groovy and Java code.

Now, your code all works but you want to put the zip of it somewhere to use. So, just add these lines:

task zip(dependsOn: jar, type: Zip) {
    from { configurations.runtime.allArtifacts.files } {
        into("${project.name}-${project.version}")
    }
    from { configurations.runtime } {
        into("${project.name}-${project.version}/lib")
    }

}


Now when you run gradle zip you will get a zip with all dependencies inside! 

Tuesday, January 27, 2015

Why am I getting "WARNING arguments left: 1"

If you are new to Akka Logging and are used to using Log4j, there is a good chance you will get the error "WARNING arguments left: 1", and not know where its coming from.

So, here it is:
In log4j, you maybe used to writing:
logger.warn("Exception caught: ", e);

This is perfectly valid and works fine. If you use this line in akka logging, you will get the error "WARNING arguments left: 1" because in the case of logback, the syntax assumes it is filling in params from the string, so it expects this:
logger.warning("Exception caught: {}", e);
Hope this will help all of us (including me) not to get caught by this again....

Spring's StringUtils -- Stuff we do with Strings all the time

The other day i was looking for a simple way to take some Strings and automatically capitalize the first character. I stumbled upon Springs StringUtils and as it turns out it has a lot of nice utility functions.

Check them out: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/util/StringUtils.html

There are many nice simple things that we need to do all the time:

  • capitalize (first characters)
  • uncapitalize
  • Lots of utilities for String arrays -- adding to them, sorting etc
Here is a really nice one: splitArrayElementsIntoProperties

Check them out!

Tuesday, December 10, 2013

Taking mocking seriously

When I first got involved in using mocks, I viewed them as a necessary evil since I had some dependencies in my class and if don’t use a mock, I will suffer NPE’s in my tests.
However, as I started using them and learning their power, I have seen that I can really use mocking in ways that enhance my unit tests. Here is a concrete example. I am using Spring Data JPA. So, I need to mock the save of my entity when it gets created in the function that I am unit testing. However, once I am mocking I can easily also validate the parameters sent to this function that did the save. Using Mockito, we use the ArgumentCaptor, to do this validation as follows:
MyRepository myRepository = mock(MyRepository.class);
ArgumentCaptor<EntityClass> argument = ArgumentCaptor.forClass(EntityClass.class);
//... invoke function to unit Test that will internally save Entity
verify(myRepository).saveAndFlush(argument.capture());
EntityClass entity = argument.getValue();
assert entity.getName().equals(“name”);
assert entity.getAddress().equals("address");

This now means my unit test has validated that all parameters passed to the function were passed to the database.
Now we see some real added value in the mock, where we can be confident that our copy of the data to the entity we are persisting has not missed any of the parameters.
Another nice feature in mocking is checking how many times a function is invoked. Modifying the the code above:
MyRepository myRepository = mock(MyRepository.class);
ArgumentCaptor<EntityClass> argument = ArgumentCaptor.forClass(EntityClass.class);
//... invoke function to unit Test that will internally save Entity
verify(myRepository,times(1)).saveAndFlush(argument.capture());
EntityClass entity = argument.getValue();
assert entity.getName().equals(name”);
assert entity.getAddress().equals("address");
Happy Mocking!

Thursday, May 26, 2011

Using Date and Calendar – At your own risk!

You can find lots of issues discussed on the ‘net about the problems of the Calendar/Date classes in Java. Here are a few that recently reared their ugly head in our code:

1. This one is actually not in either of these but in trying to output our Date. Beware of the mm instead of MM when using SimpleDateFormat. Yep, one of my team members used the following code:

SimpleDateFormat sdf = new SimpleDateFormat(“yyyymmdd”);

Surprisingly everyone in our tests had a birthday of the first of the month! I think that the right solution would be that mm is wrong and mi is minutes and mo is month. This would solve the confusion.

2. Did you know that there is a difference whether you use Calendar.HOUR or Calendar.HOUR_OF_DAY? Ok, i admit it this one is documented in the javdocs, but i would still think that it is a bit of surprise that in the afternoon, if you do

cal.set(Calendar.HOUR,0);

that you will get 12:00 PM!

3. Why does toString() of Calendar not put out the date in some format?

4. Beware that DAY_OF_WEEK is not zero based while MONTH is.

Thursday, April 28, 2011

Using StAX to extract records from an XML file

When processing large XML files, it is impossible to build a DOM of the whole file as you are sure to run out of memory. Java 6 includes StAX (it was around earlier of courser) and it is the best solution to deal with large XML files to build a scalable XML file processor. However, it still may be desirable to build a Document Model when processing an individual record due to decisions in code that may need to be made based on information lower in the node. Due to this requirement, we use StAX to extract each record from our gargantuan XML files and then pass to a different class that builds a DOM for the processing the record. Here is the very simple code with explanation of what we did.


   1: public class StaxExtracter {



   2:     XMLEventReader reader;



   3:     boolean headerRead = false;



   4:  



   5:     public void openStream(InputStream s) throws XMLStreamException {



   6:         XMLInputFactory inputFactory = XMLInputFactory.newInstance();



   7:         reader = inputFactory.createXMLEventReader(s);



   8:     }



   9:  



  10:     public void close() throws XMLStreamException {



  11:         reader.close();



  12:     }



  13:  



  14:     //function to allow us to read part of a document that does not include the header



  15:     public void setHeaderRead(boolean val) {



  16:         headerRead = val;



  17:     }


The above is some boilerplate code needed for our class. The heavy work is the XMLEventReader, created in the openStream function on line 7.

Following this we have two main functions. The first is used to read the open XML tag of the document and any important attributes in this tag, and the second is to read an actual record. Since the class is written to read recursively all sub elements of a record, it is important that we not read the open XML tag of our document as a regular record, since that will mean we wind up reading our entire document as one record! However, since there may be need to work on part of a file, i allowed an override on line 15 above so we can skip reading the header. The open XML tag is obviously not a complete XML tag so we do some heavier work here, returning the attributes as a map for use by our application, in addition to the raw line which can be used upstream in our application.

Here is the actual code:


   1: /**



   2:      * Since header is not a complete element we need to do special treatment so we will read the header attributes



   3:      * into a hashmap to save all the attributes besides returning the raw data



   4:      *



   5:      * @return the rawData of document start and header



   6:      * @throws XMLStreamException



   7:      */



   8:     public String getHeaderAndAttributesAsMap(Map<String, String> attributes) throws XMLStreamException {



   9:         boolean documentStart = false;



  10:         StringBuffer rawData = new StringBuffer();



  11:         while (reader.hasNext() && !headerRead) {



  12:             XMLEvent e = reader.nextEvent();



  13:             if (e.isStartDocument()) {



  14:                 documentStart = true;



  15:             } else if (e.isStartElement()) {



  16:                 headerRead = true;



  17:                 StartElement startElement = e.asStartElement();



  18:                 for (Iterator i = startElement.getAttributes(); i.hasNext();) {



  19:                     Attribute attr = (Attribute) i.next();



  20:                     attributes.put(attr.getName().getLocalPart(), attr.getValue());



  21:                 }



  22:             }



  23:             //skip whitespace before document



  24:             if (documentStart) {



  25:                 rawData.append(e.toString());



  26:             }



  27:         }



  28:         if (!headerRead)



  29:             return null;



  30:         else {



  31:             return rawData.toString();



  32:         }



  33:     }


Now, on to the main function for reading each element of our XML file:


   1: public enum RecordStatus {BODY,NO_DATA,CLOSE_BODY_TAG,END_DOCUMENT}



   2:  



   3: RecordStatus getNextRecord(StringBuffer recordData) throws XMLStreamException {



   4:     if (!headerRead) {



   5:         throw new RuntimeException("need to read header line before calling this function");



   6:     }



   7:     RecordStatus rc = RecordStatus.NO_DATA;



   8:     String recordName = null;



   9:     boolean finishedReadingElement = false;



  10:     boolean startOfRecord = false;



  11:     while (reader.hasNext() && !finishedReadingElement) {



  12:         XMLEvent e = reader.nextEvent();



  13:         if (e.isStartElement()) {



  14:             if (!startOfRecord) {



  15:                 startOfRecord = true;



  16:                 recordName = e.asStartElement().getName().getLocalPart();



  17:             }



  18:         } else if (e.isEndElement()) {



  19:             EndElement endElement = e.asEndElement();



  20:             if (endElement.getName().getLocalPart().equals(recordName)) {



  21:                 finishedReadingElement = true;



  22:                 rc = RecordStatus.BODY;



  23:             }  else if (!startOfRecord) {



  24:                 //todo  we could make this better by e adding validation here to save the START_BODY_TAG



  25:                 rc = RecordStatus.CLOSE_BODY_TAG;



  26:                 finishedReadingElement = true;



  27:             }



  28:         } else if (e.isEndDocument()) {



  29:             rc = RecordStatus.END_DOCUMENT;



  30:         }



  31:         //skip whitespace before element



  32:         if (startOfRecord || rc == RecordStatus.CLOSE_BODY_TAG) {



  33:             if (e.isCharacters())



  34:                 //need to re-escape characters so SAX parser wont choke on it



  35:                 recordData.append(StringEscapeUtils.escapeXml(e.toString()));



  36:             else



  37:                 recordData.append(e.toString());



  38:         }



  39:     }



  40:     return rc;



  41: }


We use an enum to give us maximal information about what was read while return the actual raw data in a StringBuffer that is allocated outside our function.

Of course, you could do ALL the parsing in your StAX implementation as well, as described here and other places, but this code allows us to continue to use the more elegant DOM for our actual work.