November 01, 2013

Quick GlassFish JNDI Custom Resources

Overview

This is a quick overview of using GlassFish JNDI Custom Resources. These are a great way to be able to provide dynamic configuration of your application at run time. When JNDI values are changed, the new values get to all cluster instances and if your code is written to lookup the values then the new values will be found the next time your code is executed by the server.

Creating a GlassFish JNDI Custom Resource

This is very easy.  The screenshot below shows how to do this with the GlassFish administration console. 
The only little trick with creating resources of java.lang.String is then name of the property must be "value".
The example shown below creates a JNDI string property bound to contactUs/emailToAddress.  The purpose of this property is to define what email address should be emailed when a user of your website fills out your company's "contact us" page.  



Getting a Glassfish JNDI Custom Resource Value

Getting a JNDI Custom Resource value from your code is very easy.  The code snippet below shows how.  By manually performing the lookup, you can ensure the code will get the latest and great value out of JNDI every time.  When using @Inject or @Resource that may not happen.
 
String emailToAddress = "";
try {
  InitialContext ic = new InitialContext();
  emailToAddress = (String) ic.lookup("contactUs/emailToAddress");
} catch (NamingException e) {
  throw new RuntimeException(e);
}

That's it. Real simple and easy.

March 29, 2013

A DIV and AngularJS Based Dropdown List Box

Introduction

I have been doing research into using AngularJS.  One of the first things I needed for my website was some nice fancy dropdown list boxes.  Of course I did not want to use regular old <select>, what would be the fun in that.  So I set out to build one using DIVs and AngularJS.  This little demo shows the results of my research.

Download Source Code: div-and-angularjs-dropdown-lists.zip

Demo

Below the demo is running in an IFRAME. It may not display the best. If you want you can visit the full page demo at http://ferris.sourceforge.net/div-and-angularjs-dropdown-lists

March 11, 2013

JAXB Unmarshalling To a Sorted Map

Introduction

While using JAXB for my last project, I came across the need to access a list of data in two ways.  First, the data was to be accessed as a sorted list with the sort order being determined by the /Book[@SortOrder] attribute. Second, the data was to be access as a map, supplying a key value from /Book[@Id] to get a specific book by key. With these two requirements, a LinkedHashMap object is clearly the way to go. Book objects are added to the LinkedHashMap in /Book[@SortOrder] order and /Book[@Id] is the map key. My initial thought was to let JAXB unmarshal the XML into a regular List then as a post processing step I would reorder the list and create a map.  But the more I thought about this the more I didn't like this solution.  Since JAXB is doing the work of unmarshalling the XML, I figured JAXB should be able to put it into a LinkedHashMap like I wanted. The purpose of this article is to demonstrate how to get JAXB to create a LinkedHashMap for you so you can access a list of data in both by key and as a correctly sorted list.

The XML

 Let's first consider a simple XML document to demonstrate what's needed.  Below is sample XML document representing search results for books. The list of books has a [@SortOrder] and an [@Id].  The application will need to be able to display the books in the correct sort order but also be able to lookup books quickly by id.
<SearchResults>
    <Books>
        <Book Id="794N-98" SortOrder="5">
            <Title>Open to the Sky</Title>
        </Book> 
        <Book Id="998X-78" SortOrder="2">
            <Title>Mars, Friend or Foe?</Title>
        </Book>
        <Book Id="445M-09" SortOrder="3">
            <Title>Jumping Beans Jump</Title>
        </Book>  
        <Book Id="002I-11" SortOrder="1">
            <Title>Little Worms Go To School</Title>
        </Book> 
        <Book Id="951G-42" SortOrder="4">
            <Title>America, The Early Years</Title>
        </Book> 
    </Books>
</SearchResults>


The Classes

In order to get JAXB to create a LinkedHashMap for you automatically, you will need need the following classes, with the BooksAdapter class one really doing all of the work for you:

SearchResults.java

Unmarshalled object for the <SearchResults> tag
@XmlRootElement(name="SearchResults")
public class SearchResults 
{
	@XmlElement(name="Books")
	@XmlJavaTypeAdapter(BooksAdapter.class)
	private Map<String, Book> books;
	public Map<String, Book> getBooksMap() {
		return books;
	}
	
	public List<Book> getBooksList() {
		return new ArrayList<Book>(books.values());
	}
}

Books.java

Unmarshalled object for the <Books> tag. This is initially needed by JAXB to convert all of the <Book>  elements into a list.  This class is then later used by BooksAdapter to convert it into a LinkedHashMap.
@XmlRootElement(name="Books")
public class Books 
{
	private List<Book> books;
	
	@XmlElement(name="Book")
	public List<Book> getBooks() {
		return books;
	}
	
	public void setBooks(List<Book> books) {
		this.books = books;
	}
}

Book.java

Unmarshalled object for the <Book> tag
@XmlRootElement(name="Book")
public class Book 
{
	@XmlAttribute(name="SortOrder")
	private Integer sortOrder;
	public Integer getSortOrder() {
		return sortOrder;
	}

	
	@XmlAttribute(name="Id")
	private String id;
	public String getId() {
		return id;
	}
	
	@XmlElement(name="Title")
	private String title;
	public String getTitle() {
		return title;
	}
}

BooksAdapter.java

An XmlAdapter implementation which converts the Books object into a LinkedHashMap object where the Book objects are put into the map by key /Book[@Id] and in the order specified by /Book[@SortOrder]. 
public class BooksAdapter extends XmlAdapter<Books, Map<String, Book>> {
	
	@Override
	public Map<String, Book> unmarshal(Books books) throws Exception {
		Collections.sort(books.getBooks(), new BookComparatorBySortOrder());
		Map<String, Book> map = new LinkedHashMap<String,Book>();
        for (Book book : books.getBooks()) {
            map.put(book.getId(), book);
        }
        return map;
	}

	@Override
	public Books marshal(Map<String, Book> map) throws Exception {
		Books books = new Books();
		books.setBooks(new LinkedList<Book>(map.values()));
		return books;
	}
}

class BookComparatorBySortOrder implements Comparator<Book> {
	@Override
	public int compare(Book o1, Book o2) {
		return o1.getSortOrder().compareTo(o2.getSortOrder());
	}
	
}

 

Testing

Testing this is pretty easy, just supply the XML document and have JAXB do it's thing. Here is a unit test:

SearchResultsTest.java 

public class SearchResultsTest 
{
	private SearchResults searchResults; 
	
	@Before
	public void before() throws Exception 
	{
		// Read file from classpath
		String filename = "/SearchResults.xml";
    	InputStream istream = getClass().getResourceAsStream(filename);
    	assertNotNull(String.format("Cannot find classpath resource \"%s\"", filename), istream);
    	
    	// Prepare JAXB objects
		JAXBContext jc = JAXBContext.newInstance(SearchResults.class);
		Unmarshaller u = jc.createUnmarshaller();

		// Prepare the input
		InputSource isource = new InputSource(istream);

		// Do unmarshalling
		searchResults = (SearchResults)u.unmarshal(isource);
		
        assertNotNull(String.format("Unmarshal returned null for SearchResults object"), searchResults);
        
        istream.close();
        istream = null;
	}
	
	@Test
	public void testBookFindById() 
	{
		
		Map<String, Book> books = searchResults.getBooksMap();
		assertNotNull(books);
		assertEquals(5, books.size());
		
		assertEquals("Little Worms Go To School",books.get("002I-11").getTitle());
		assertEquals("Mars, Friend or Foe?", 	 books.get("998X-78").getTitle());
		assertEquals("Jumpping Beans Jump", 	 books.get("445M-09").getTitle());
		assertEquals("America, The Early Years", books.get("951G-42").getTitle());
		assertEquals("Open to the Sky", 		 books.get("794N-98").getTitle());	
	}
	
	@Test
	public void testBookSorted() 
	{
		
		List<Book> books = searchResults.getBooksList();
		assertNotNull(books);
		assertEquals(5, books.size());
		
		assertEquals(new Integer(1), books.get(0).getSortOrder());
		assertEquals(new Integer(2), books.get(1).getSortOrder());
		assertEquals(new Integer(3), books.get(2).getSortOrder());
		assertEquals(new Integer(4), books.get(3).getSortOrder());
		assertEquals(new Integer(5), books.get(4).getSortOrder());		
	}

}

Download

You can download a Maven project of this from sourceforge:

http://ferris.cvs.sourceforge.net/viewvc/ferris/ferris-jaxb-sortedmap/