Tag Archives: Java

Ajax + Servlet

Introduction

Found myself with some spare time on my hands and decided to figure out how Ajax works and develop a little example for the blog seeing that I haven’t updated since near infinity in Internet time.

Ajax

Ajax (AJAX) stands for Asynchronous JavaScript and XML. It is a technique using JavaScript and server objects to change webpage content only for a specific piece of the webpage without refreshing the whole page. This is different from normal JavaScript because the change includes an exchange of data with the server. This allows access to services that are found on a server like databases and business logic. Users have an experience that is more interactive. A good example would be a series of pictures being displayed that are only accessible from a database. Each time a picture is clicked it changes to a new picture.

An Ajax request has two major parts, the request and the interactive server portion that hands out the data the request wants. The request creates a XMLHttpRequest and sends the request as a standard html post or get. The server responds in kind with XML. If done right, this draws a hard line between the presentation layer and the business layer. This is not a new idea. JSPs have backing beans. Thick clients have remote objects (RMI anyone?). Ajax in my opinion goes farther by removing the need for a specific type of server side support it needs. It doesn’t care if it is PHP or a Servlet. All it cares for is the contract to be fulfilled. This creates a situation where the implementation of the server objects can change completely and the webpage won’t care. That’s right, one day a bunch of server scripts can be used and then six months later, a set of servlets can be used to replace them. That is an extreme example because of having to stand up a web container in place of the server that supports scripts but a lot of the mapping requests to the server can be done rather painlessly using servlet mapping.

Example

Let’s get to an example of Ajax in action. This example updates three fields with the time from different time zones. The first one is local time, the second is GMT and the last time is for New York. I am using a JavaScript library named jQuery to help write the JavaScript and the Ajax request. For more information on jQuery, go to http://jquery.com/. Since this is a Java blog, the server object is a servlet named TimeServlet.java. All the code can be downloaded from https://github.com/darylmathison/time-ajax-example. The example was created in Eclipse so Eclipse users can import it as a project. The web container I used is a Tomcat 5.5 server.

Webpage

Here is the webpage that makes the requests to the server object. It puts the current time from three different time zones into an html table beneath the label of the time zone it represents. The current time is displayed every time the “Show Times” button is clicked.

<html>

<head>

<meta http-equiv=“Content-Type” content=“text/html; charset=ISO-8859-1”>

<title>AJAX Timetitle>

<script type=“text/javascript” src=“jquery.js”>script>

<script type=“text/javascript”>

$(document).ready(function() {

var timeid = “timeid”;

$(“#timebutton”).click(function() {

$(“#local”).load(‘/TimeAjax/TimeServlet’, {timeid: “local”});

$(“#GMT”).load(“/TimeAjax/TimeServlet”, {timeid: “GMT”});

$(“#newyork”).load(“/TimeAjax/TimeServlet”, {timeid: “newyork”});

});

$(“#errorMsg”).ajaxError(function(event, request, settings, error){

$(this).append(“ajax call failed: “ + settings.url);

alert(settings.url);

});

});

script>

head>

<body>

<table>

<tr>

<td>Local Timetd>

<td>GMT Timetd>

<td>New York Timetd>

tr>

<tr>

<td><span id=“local”> span>td>

<td><span id=“GMT”> span>td>

<td><span id=“newyork”> span>td>

tr>

<tr>

<td colspan=“3”><div id=“errorMsg”>div>td>

tr>

table>

<button id=“timebutton”>Show Timesbutton>

body>

html>

The load function is where the actual request happens.

$(“#local”).load(‘/TimeAjax/TimeServlet’, {timeid: “local”});

$(“#GMT”).load(“/TimeAjax/TimeServlet”, {timeid: “GMT”});

$(“#newyork”).load(“/TimeAjax/TimeServlet”, {timeid: “newyork”});

This is a series of requests for items that have the id of local, GMT and newyork respectively. They all call the servlet with different timeids to tell the servlet what time zone to display back. These requests are sent out when the “Show Times” button is clicked.

<td><span id=“local”> span>td>

<td><span id=“GMT”> span>td>

<td><span id=“newyork”> span>td>

These are the three table cells that are going to be changed when the responses come back.

Servlet

Here is the code for the TimeServlet that services the requests from the webpage. It grabs the timeid from the request and uses java.text.SimpleDateFormat to format the current time into the respective time zone.

public class TimeServlet extends HttpServlet {

private static final long serialVersionUID = 1L;


/**

* Default constructor.

*/

public TimeServlet() {
// TODO Auto-generated constructor stub

}

/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String timeid = request.getParameter(“timeid”);

System.out.println(“timeid is “ + timeid);

if (timeid != null && timeid.length() > 0 ) {

response.setContentType(“text/xml”);

response.setHeader(“Cache-Control”, “no-cache”);

Calendar cal = null;

String dateformat = “HH:mm”;

SimpleDateFormat format = null;


if (“local”.equals(timeid)) {

System.out.println(“in local”);

cal = Calendar.getInstance();

format = new SimpleDateFormat(dateformat);

response.getWriter().write(“” +

format.format(cal.getTime())+ “”);

} else if(“GMT”.equals(timeid)) {

cal = Calendar.getInstance();

format = new SimpleDateFormat(dateformat);

format.setTimeZone(TimeZone.getTimeZone(“GMT”));

response.getWriter().write(“” + format.format(cal.getTime()) + “”);

} else if(“newyork”.equals(timeid)) {

TimeZone tz = TimeZone.getTimeZone(“America/New_York”);

cal = Calendar.getInstance();

format = new SimpleDateFormat(dateformat);

format.setTimeZone(tz);

response.getWriter().write(“” + format.format(cal.getTime())+ “”);

} else {

response.getWriter().write(“cannot find timeid”);

}

} else {

response.getWriter().write(“there is no timeid”);

}

}

/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

*/

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

doGet(request, response);

}

}

The real work happens in the doGet method.

String timeid = request.getParameter(“timeid”);

Here is where the timeid passed from the Ajax request is pulled from the HttpServletRequest. The passed timeid variable is tested for validity to ward off any NullPointerExceptions.

The below code details what I did to display the time for the local time zone.

if (“local”.equals(timeid)) {

System.out.println(“in local”);

cal = Calendar.getInstance();

format = new SimpleDateFormat(dateformat);

response.getWriter().write(“” + format.format(cal.getTime())+ “”);

}

This is easy because Java defaults to the local locale and time zone. It gets trickier for GMT and the New York time zones but not too much because all that needs to happen is setting the time zone of the formatter.

else if(“GMT”.equals(timeid)) {

cal = Calendar.getInstance();

format = new SimpleDateFormat(dateformat);

format.setTimeZone(TimeZone.getTimeZone(“GMT”));

response.getWriter().write(“” + format.format(cal.getTime()) + “”);

}

This is repeated for the New York time zone using the “America/New_York” time zone.

Last Thoughts

This is another tool in the toolbox for web development. It allows web components to be more interactive enhancing the user experience on your website. It can also be used to further separate presentation and business logic. If you have any comments or questions about this post, please leave them below.

Advertisement

Technologies I am Working on

I have been combining technologies for my For the Little Guy application described in the documents in the download section. Next post I am going to give a demonstration of how I combined Eclipse, Spring Framework and Maven. Currently work has been quite demanding so I have slipped on posts. Here are some links I have been using to make it all work.

Maven – http://maven.apache.com

Spring Framework – http://www.springsource.com/

Eclipse – http://www.eclipse.org

Maven Eclipse Tools – http://www.eclipse.org/m2e/

Searching Jars

I have run into the problem where I am looking for the right jar file from a production environment and bring it to a development environment. The problem is that when I get the ClassNotFoundException or the “I can’t find this class” error from the compiler, the right jar file does not come out and say, “Include me in your classpath!” To solve that problem I created an application to do it. It searches recursively through directories and finds all the jar files. Once it finds a jar file, the jar file is opened and a regex search is done to the names to find the missing resource. If the resource is found, the jar file that contains the resource is returned. Otherwise, null is printed on the screen. Below is the class file:

public class JarsSearch {

public static final String FILE_PARAM = “–file”;

public static final String ROOT_PARAM = “–root”;

public static final String HELP_PARAM_PATTERN = “-? | –help”;


public static final String DEFAULT_ROOT = “.”;


private String filename;

private String rootpath = DEFAULT_ROOT;

public JarsSearch() {}


public JarsSearch(String root, String filename) {

setRootpath(root);

setFilename(filename);

}

/**

* @return the filename

*/

public String getFilename() {

return filename;

}

/**

* @param filename the filename to set

*/

public void setFilename(String filename) {

this.filename = filename;

}

/**

* @return the rootpath

*/

public String getRootpath() {

return rootpath;

}

/**

* @param rootpath the rootpath to set

*/

public void setRootpath(String rootpath) {

this.rootpath = rootpath;

}

/**

* looks for the file on any jar under the rootpath

*

* @return String the path of the containing jar file

*/

public String find() {

String jarFilename = null;


try {

File[] jarsNdirs = new File(getRootpath()).listFiles(new JarFileFilter());

Arrays.sort(jarsNdirs, new ListingComparator());

for (File f: jarsNdirs) {

if (f.isDirectory()) {

JarsSearch js = new JarsSearch(f.getCanonicalPath(), getFilename());

jarFilename = js.find();

if (Utils.isStringValid(jarFilename)) {

break;

}

} else { // if not a directory, then a jar file

JarEntry entry;

Pattern p = Pattern.compile(getFilename());

Matcher m = null;


JarFile jarFile = new JarFile(f, false, JarFile.OPEN_READ);

Enumeration e = jarFile.entries();

while (e.hasMoreElements()) {

entry = e.nextElement();

//System.out.println(“printing entry name: ” + entry.getName());

m = p.matcher(entry.getName());

if (m.matches()) {

jarFilename = f.getCanonicalPath();

}

}

jarFile.close();

}

}

} catch (Exception e) {

e.printStackTrace();

}


return jarFilename;

}


public String toString() {

return “JarsSearch[ filename pattern – “ + getFilename() + “, root path – “ + getRootpath() + ” ]”;

}


/**

* @param args

*/

public static void main(String[] args) {

String filepattern = null;

String rootdir = null;


for(int i = 0; i < args.length; i++) {

if (args[i].matches(HELP_PARAM_PATTERN)) {

showArgs();

} else if (args[i].matches(FILE_PARAM)) {

if ((i + 1) < args.length) {

filepattern = args[i + 1];

i++;

continue;

}

} else if (args[i].matches(ROOT_PARAM)) {

if ((i + 1) < args.length) {

rootdir = args[i + 1];

i++;

continue;

}

} else {

showArgs();

}

}


JarsSearch js = new JarsSearch();

if (!Utils.isStringValid(filepattern) || ROOT_PARAM.equals(filepattern)) {

showArgs();

} else {

js.setFilename(filepattern.trim());

}

if (Utils.isStringValid(rootdir) && !FILE_PARAM.equals(rootdir)) {

js.setRootpath(rootdir.trim());

}


System.out.println(js.find());

System.exit(0);

}


protected static void showArgs() {

System.out.println(“–help: this listing”);

System.out.println(“-? : this listing”);

System.out.println(ROOT_PARAM + “: where to start looking from. Default = ‘.'”);

System.out.println(FILE_PARAM + “: regex pattern of a file to look for in a jar file”);

System.exit(0);

}

}

class JarFileFilter implements java.io.FileFilter {

public boolean accept(File arg0) {

String name = arg0.getName();

return ( arg0.canRead() && ( arg0.isDirectory() || name.endsWith(“jar”) ) );

}


}

class ListingComparator implements java.util.Comparator {

public int compare(File arg0, File arg1) {

if (arg0.isDirectory() && !arg1.isDirectory()) {

return -1;

} else if (!arg0.isDirectory() && arg1.isDirectory()) {

return 1;

} else { // ( (arg0.isDirectory() && arg1.isDirectory()) || (arg0.isFile() && arg1.isFile()) )

return arg0.compareTo(arg1);

}

}


}

To get a complete copy of all the source code found on this post, go to https://github.com/darylmathison/jar-search-example.

Using the Java Naming and Directory Interface (JNDI) (Part 3)

Introduction

In the last two posts about using JNDI, I have shown examples of how one can get and add information in a number of ways. The first post discussed LDAP servers and showed a quick program one could use to retrieve entries stored in the server.  The entry was represented as a collection of attributes.  The second post demonstrated a number of ways to store and retrieve Java objects on the server.  The two examples demonstrated how objects could be saved in base-64 or as a reference to another object.  This post will demonstrate how a set of attributes can be turned into a Java object and how to store that object as a set of attributes.

Setup

To make a Java object get saved as a set of entry attributes, I have to refactor the User class.  By implementing the DirContext, the class will organize itself into a set of attributes. Here is the new version of User, AttrUser.

public class AttrUser extends DirContextAdapter {

public static final String INIT_VALUE = “none”;

public static final String NAME_ATTR = “cn”;

public static final String UID_ATTR = “uid”;

public static final String EMAIL_ATTR = “mail”;

public static final String SN_ATTR = “sn”;

private Attributes attrs;


public AttrUser() {

attrs = new BasicAttributes(true);

Attribute oc = new BasicAttribute(“objectclass”);

oc.add(“inetOrgPerson”);

oc.add(“top”);


attrs.put(oc);

attrs.put(NAME_ATTR, INIT_VALUE);

attrs.put(UID_ATTR, INIT_VALUE);

attrs.put(EMAIL_ATTR, INIT_VALUE);

attrs.put(SN_ATTR, INIT_VALUE);

}

public String getName() {

String name = null;

try {

Attribute a = attrs.get(NAME_ATTR);

name = a.get().toString();

} catch (NamingException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return name;

}


public void setName(String name) {

Attribute a = attrs.get(NAME_ATTR);

a.clear();

a.add(name);

}


public String getUserid() {

String userid = null;

try {

Attribute a = attrs.get(UID_ATTR);

userid = a.get().toString();

} catch(NamingException ne) {

ne.printStackTrace();

}

return userid;

}


public void setUserid(String userid) {

Attribute a = attrs.get(UID_ATTR);

a.clear();

a.add(userid);

}


public String getEmail() {

String email = null;

try {

Attribute a = attrs.get(EMAIL_ATTR);

email = a.get().toString();

} catch(NamingException ne) {

ne.printStackTrace();

}

return email;

}

public void setEmail(String email) {

Attribute a = attrs.get(EMAIL_ATTR);

a.clear();

a.add(email);

}


public void setLastname(String lastname) {

Attribute a = attrs.get(SN_ATTR);

a.clear();

a.add(lastname);

}


public String getLastname() {

String lastname = null;

try {

Attribute a = attrs.get(SN_ATTR);

lastname = a.get().toString();

} catch(NamingException ne) {

ne.printStackTrace();

}

return lastname;

}

public Attributes getAttributes(Name arg0) throws NamingException {

return getAttributes(arg0.toString());

}


public Attributes getAttributes(String arg0) throws NamingException {

if(arg0 != null && arg0.length() != 0) {

throw new NameNotFoundException();

}

return (Attributes)attrs.clone();

}


@Override

public Attributes getAttributes(Name arg0, String[] arg1) throws NamingException {

return getAttributes(arg0.toString(), arg1);

}


@Override

public Attributes getAttributes(String arg0, String[] arg1) throws NamingException {

if (arg0 != null && arg0.length() > 0) {

throw new NameNotFoundException();

}

Attributes ret = new BasicAttributes(true);


for (String id: arg1) {

ret.put(attrs.get(id));

}

return ret;

}

}

The class looks a lot different now. Notice that backed the whole class with an instance of Attributes.  I thought the code looked cleaner that way.  Also notice that I extended a DirContextAdapter instead of implementing DirContext.  To keep clean looking code, created an adapter.   Another reason is because the context provider looks to store java objects in a certain order. The provider will look to store a java object as a reference first, serialized second and a context third.  So If I had extended User.java, the example would have not worked.  Another small difference is I now added lastname as one of the attributes to store.  Lastname is a required attribute of InetOrgPerson, and since I want AttrUser to be accepted like an InetOrgPerson, it needs to keep track like one. The other class needed is the factory that will turn the context attributes back into an AttrUser.

public class AttrUserFactory implements DirObjectFactory {

@Override

public Object getObjectInstance(Object arg0, Name arg1, Context arg2,

Hashtable arg3) throws Exception {

// because this is for an attributes based object, this factory method simply returns null.

return null;

}

@Override

public Object getObjectInstance(Object arg0, Name arg1, Context arg2, Hashtable arg3, Attributes arg4) throws Exception {

AttrUser u = null;

if (checkObject(arg0, arg4)) {

u = new AttrUser();

Attribute a = arg4.get(AttrUser.NAME_ATTR);

u.setName(a.get().toString());


a = arg4.get(AttrUser.UID_ATTR);

u.setUserid(a.get().toString());


a = arg4.get(AttrUser.EMAIL_ATTR);

u.setEmail(a.get().toString());


a = arg4.get(AttrUser.SN_ATTR);

u.setLastname(a.get().toString());

}

return u;

}


private boolean checkObject(Object o, Attributes att) {

boolean isAttrUser = false;


if (o instanceof DirContext) {

if(att != null && att.size() >= 4) {

boolean areAttrThere = true;

areAttrThere &= (att.get(AttrUser.NAME_ATTR) != null);

areAttrThere &= (att.get(AttrUser.SN_ATTR) != null);

areAttrThere &= (att.get(AttrUser.EMAIL_ATTR) != null);

areAttrThere &= (att.get(AttrUser.UID_ATTR) != null);

isAttrUser = areAttrThere;

}

}

return isAttrUser;

}

}

This class implements the same DirObjectFactory as the last time but fills out the attribute based function. According to the DirObjectFactory contract, the function needs to return null if it is not a match for that data. Context providers can handle a range of factories.  It goes to each one and runs the factory call.  If the returned value is non-null or an exception, the traversal ends and it returns the value or allows the exception to be caught.  The setup is done, lets put it all together.

The Lookup

public class AttributeLookup {

static Hashtable<String, String> getEnv() {

Hashtable<String, String> env = new Hashtable<String, String>();

env.put(Context.INITIAL_CONTEXT_FACTORY, “com.sun.jndi.ldap.LdapCtxFactory”);

env.put(Context.PROVIDER_URL, “ldap://localhost:10389/ou=Users,dc=example,dc=com”);

env.put(Context.OBJECT_FACTORIES, AttrUserFactory.class.getName());


return env;

}

public static void main(String[] args) {

DirContext ctx = null;

try {

ctx = new InitialDirContext(getEnv());


AttrUser user = new AttrUser();

user.setEmail(“joey@example.com”);

user.setLastname(“Bourne”);

user.setName(“Joey”);

user.setUserid(“joey”);


ctx.rebind(“uid=” + user.getUserid(), user);

// read

AttrUser newUser = (AttrUser)ctx.lookup(“uid=” + user.getUserid());

System.out.println(“email is “ + newUser.getEmail());


} catch (NamingException e) {

e.printStackTrace();

}

finally{

try {

ctx.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

This looks a lot like the other examples that I have covered. The one exception is where I defined my object factory. If I did not include the object factory, the lookup would have returned a set of Attributes like on the first example. The data stored in the server shows this to be true.

dn: uid=joey,ou=Users,dc=example,dc=com

objectClass: organizationalPerson

objectClass: person

objectClass: inetOrgPerson

objectClass: top

cn: Joey

sn: Bourne

mail: joey@example.com

uid: joey

In fact, I could have just used the object factory and read any user entry from the server and have the entries turned into AttrUser objects and not have to worry about implementing DirContext.

That was Fun

That is the last demonstration I have right now for JNDI.  I have shown a simple entry lookup, how to store a Java Object directly and indirectly on the server to objects that create entries and those entries can be read back into a Java object.  If you have anymore JNDI knowledge to share, leave a comment.  The source code can be found at https://github.com/darylmathison/jndi-example.

Spring into Action

Pardon the pun.  I was doing some research on the Spring Framework when I found these links.  Yes they are 5 years old but it still got me thinking in Spring.

The Spring series, Part 1: Introduction to the Spring framework

The Spring series, Part 2: When Hibernate meets Spring

The Spring series, Part 3: Swing into Spring MVC

The Spring series, Part 4: 1-2-3 messaging with Spring JMS

Using the Java Naming and Directory Interface (JNDI) (Part 2)

In my last post, I discussed directory servers and a quick example of how to query them. To read part one click here. JNDI can be used to store whole objects into a LDAP server. In this entry, a java object will be stored on the server directly.

First example uses a mechanism that Java has had since the beginning, serialization. I need to define a user class. The following class is from User.java:

public class User implements Serializable {

private static final long serialVersionUID = 3999866113934116781L;

private String name;

private String userid;

private String email;


public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getUserid() {

return userid;

}

public void setUserid(String userid) {

this.userid = userid;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

}

It is just a number of setters and getters for a name, user id and email. It does implement java.io.Serializable to make it work for storage. Here is the class that uses User.java.

public class JavaObjectLookup {

static Hashtable<String, String> getEnv() {

Hashtable<String, String> env = new Hashtable<String, String>();

env.put(Context.INITIAL_CONTEXT_FACTORY, “com.sun.jndi.ldap.LdapCtxFactory”);

env.put(Context.PROVIDER_URL, “ldap://localhost:10389/ou=java,dc=example,dc=com”);

return env;

}

public static void main(String[] args) {

DirContext ctx = null;

try {

ctx = new InitialDirContext(getEnv());

// first bind an object to the Directory

User user = new User();

user.setName(“Joey”);

user.setUserid(“joey”);

user.setEmail(“joey@example.com”);


ctx.bind(“cn=joey”, user);


User u = (User)ctx.lookup(“cn=joey”);


System.out.println( “User’s email is “ + u.getEmail());

} catch (NamingException e) {

e.printStackTrace();

}

finally {

try {

ctx.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}


Notice that the connection URL has been changed to “ou=java,dc=example,dc=com” so the object will be put into the java organizational unit. On the LDAP server, the entry looks like the following:

dn: cn=joey,ou=java,dc=example,dc=com

objectClass: javaSerializedObject

objectClass: javaObject

objectClass: javaContainer

objectClass: top

cn: joey

javaClassName: org.mathison.example.jndi.User

javaSerializedData:: rO0ABXNyAB5vcmcubWF0aGlzb24uZXhhbXBsZS5qbmRpLlVzZXI3gmE

J1ipHrQIAA0wABWVtYWlsdAASTGphdmEvbGFuZy9TdHJpbmc7TAAEbmFtZXEAfgABTAAGdXNlcm

lkcQB+AAF4cHQAEGpvZXlAZXhhbXBsZS5jb210AARKb2V5dAAEam9leQ==

javaClassNames: org.mathison.example.jndi.User

javaClassNames: java.lang.Object

javaClassNames: java.io.Serializable

The instance is stored as a base-64 encoded string. This is good for storing an instance that a lot of different java processes will access such as a printer driver. But what if a service wants to register its services on a LDAP server? It is no good to store a copy of a service on a directory server because a service is only useful if it can serve. It would be better if the entry just “referred” at the service rather being a copy of it. This is the rational for using javax.naming.Reference. To store a reference, a developer can have the class implement java.naming.Referenceable and call bind on the object or create a reference and bind the reference. On retrieving the reference, a developer can create an object from the information in the reference instance. If an object factory is used, the lookup returns an instance of your class. The following example has ReferUser that implements Referencable and uses an object factory.

Example code:

public class JavaObjectRefLookup {


static Hashtable<String, String> getEnv() {

Hashtable<String, String> env = new Hashtable<String, String>();


env.put(Context.INITIAL_CONTEXT_FACTORY, “com.sun.jndi.ldap.LdapCtxFactory”);

env.put(Context.PROVIDER_URL, “ldap://localhost:10389/ou=java,dc=example,dc=com”);


return env;

}

/**

* @param args

*/

public static void main(String[] args) {

DirContext ctx = null;

try {

ctx = new InitialDirContext(getEnv());


// first bind an object to the Directory

ReferUser user = new ReferUser();

user.setName(“Joey”);

user.setUserid(“joey”);

user.setEmail(“joey@example.com”);


ctx.rebind(“cn=joey”, user);


ReferUser u = (ReferUser)ctx.lookup(“cn=joey”);


System.out.println( “User’s email is “ + u.getEmail());

} catch (NamingException e) {

e.printStackTrace();

}

finally{

try {

ctx.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

import org.mathison.jndi.example2.User;

public class ReferUser extends User implements Referenceable {

public Reference getReference() throws NamingException {

Reference ref = new Reference(this.getClass().getName(),

ReferUserFactory.class.getName(), null);

ref.add(new StringRefAddr(“name”, getName()));

ref.add(new StringRefAddr(“mail”, getEmail()));

ref.add(new StringRefAddr(“uid”, getUserid()));

return ref;

}

}

import javax.naming.directory.Attributes;

import javax.naming.spi.DirObjectFactory;

public class ReferUserFactory implements DirObjectFactory {

@Override

public Object getObjectInstance(Object arg0, Name arg1, Context arg2, Hashtable arg3, Attributes arg4) throws Exception {

return getObjectInstance(arg0, arg1, arg2, arg3);

}

@Override

public Object getObjectInstance(Object arg0, Name arg1, Context arg2, Hashtable arg3) throws Exception {

ReferUser user = null;

if (arg0 instanceof Reference){

Reference ref = (Reference)arg0;

if(ref.getClassName().equals(ReferUser.class.getName())) {

RefAddr name = ref.get(“name”);

RefAddr uid = ref.get(“uid”);

RefAddr email = ref.get(“mail”);


user = new ReferUser();

user.setName(name.getContent().toString());

user.setEmail(email.getContent().toString());

user.setUserid(uid.getContent().toString());

}

}

return user;

}

}

Here is what you will find if you take a look at the Directory Server:

dn: cn=joey,ou=java,dc=example,dc=com

objectClass: javaContainer

objectClass: javaNamingReference

objectClass: javaObject

objectClass: top

cn: joey

javaClassName: org.mathison.example.jndi.ReferUser

javaFactory: org.mathison.example.jndi.ReferUserFactory

javaReferenceAddress: #0#name#Joey

javaReferenceAddress: #1#mail#joey@example.com

javaReferenceAddress: #2#uid#joey

Notice that the object’s attributes are now stored in javaReferenceAddress attributes. Also notice how each of these techniques used special java storage attributes to the job done. Well, the next part of this blog series will tackle creating a object without special java structures. All of this code can be downloaded from https://github.com/darylmathison/jndi-example via subversion or your browser.

Using the Java Naming and Directory Interface (JNDI) (Part 1)

Been learning a lot at my new job at St. Mary’s University. The university has been able to serve the students, faculty and staff via the “Gateway.” The Gateway is a portal site using a Luminis system from SunGuard. SunGuard based their system on uPortal. One of the central servers is a LDAP server. It contains course information, user information, department information, information about the current term and permission groups. With this much importance on one server I thought it would be a good idea to learn about it and how Java could interact with it.

First some background into LDAP.   LDAP stands for Lightwieght DirectoryAccess Protocol. LDAP servers are a type of Directory Server witch hold collections of information(well like a directory). Good examples are phone directories. The difference between a phone directory and a directory server is that a directory server can hold a directory of any data rather than contact information. They are not replacements for relational databases. Directory servers are not designed to handle generalized data relationships like relational databases. One needs to think more one-to-one or one-to-many data sets for LDAP servers. Another difference is the speed of reading vs. writing. Most directory servers are very fast on reading data but slow on writing.  Each LDAP entry has a distinguished name or dn.  This is the key of the entry.  It is normally composed of multiple parts of attributes found in the entry.  The other part of an entry is attributes.  Attributes have a name and a value.  For example, an entry with a dn of “uid=mborn, ou=Users, dc=example, dc=com” has an attribute named common name or cn that has the value “Max Born.”  There can be multiple values for each attribute.  In the last example, there are multiple objectClass attributes, each one with a unique value.  ObjectClasses are important for LDAP entries because they define what attributes an entry can contain or have to contain.  ObjectClasses are defined in schemas.  Normally, these files are separate from the normal configuration files.  Many of the schemas used in LDAP servers are standardized so as long as the LDAP server supports a schema.  The schemas that the examples use are InetOrgPerson and Java.

To run the examples, I suggest downloading and installing both sub projects from The Apache Directory Project. The Apache Directory Studio alone makes the effort worth it. The studio is LDAPv3 compliant so any LDAPv3 server can be used. I started using it on OpenLDAP because I bought “Mastering OpenLDAP” researching this subject. I switched over to Apache’s Directory because of how easy it was to use with the studio in a Microsoft Windows environment. I used the example.ldif file contained the directory server’s configuration directory. The only modification to the file was removing the users that used references. I also added an organzational unit named java to save the java objects into. I also suggest downloading and installing a JDKv1.3 or later. Java 1.3 and newer already contain the JNDI libraries that will be used throughout. I developed these examples using Java 1.6.

Here is the first example, all this does is connect to a server anonymously and find the user associated with a uid of mborn.

package org.mathison.example.jndi;

import javax.naming.Context;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.DirContext;
import javax.naming.directory.Attributes;
import javax.naming.NamingException;

import java.util.Hashtable;

public class JndiClient {

static Hashtable getEnv() {
Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY, “com.sun.jndi.ldap.LdapCtxFactory”);
env.put(Context.PROVIDER_URL, “ldap://localhost:10389/dc=example,dc=com”);

return env;

}

/**
* @param args

*/
public static void main(String[] args) {

try {

DirContext ctx = new InitialDirContext(getEnv());
Attributes attr = ctx.getAttributes(“uid=mborn,ou=Users”);
System.out.println(“Mborn’s name is ” + attr.get(“cn”).get());
ctx.close();

} catch (NamingException e) {

e.printStackTrace();

}

}

}

First thing that happens is creating an DirContext.  For this an instance of Hashtable is passed to the InitialDirContext.  The hashtable sets up the Context that is used and where it will connect.  The URL has two parts, the address to the server and the directory in the server.  All of the entries that are written to or read from are assumed to be in that directory.  The next line returns the attributes for the entry that has a user id of mborn and is in the users organizational unit.  The System.out line retrieves the “cn” or common name from the entry and prints it out to the screen.  All of this is wrapped in a try-catch block in case a NamingException is thrown.  This is the basic query and retrieve from a LDAP server and is most of what happens.

While JNDI is excellent at pulling attributes from a LDAP server, its real power comes from when one starts storing Java objects on the server. That will be discussed on the next entry.

Links to resources used for this article:
JNDI Tutorial
Mastering OpenLDAP
The Apache Directory Project

Welcome

Big Hello!!

First a little about myself. I have been developing some part of an enterprise system in Java since 1998. I have had experience with RMI, JDBC, Swing, Servlets, ADF, and OAF. I am currently studying for my Sun Certification Java Programmer 6. Here are some links I have found useful in Java developing:

http://java.sun.com – This is ground zero for Java Development news and links.

http://java.sun.com/javase/6/docs/api/ – API Specification for Java 6 SE.  I have this page always open when I am programming.

http://java.sun.com/javase/downloads/index.jsp – Download JDKs, documentation and development bundles.

Those are what I can think of now.  I will post more as I think of them.