Index: jnpserver/src/test/java/org/jnp/server/test/jbname42/MissingObjectFactoryBindingTestCase.java
===================================================================
--- jnpserver/src/test/java/org/jnp/server/test/jbname42/MissingObjectFactoryBindingTestCase.java	(revision 0)
+++ jnpserver/src/test/java/org/jnp/server/test/jbname42/MissingObjectFactoryBindingTestCase.java	(revision 0)
@@ -0,0 +1,182 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jnp.server.test.jbname42;
+
+import java.util.Hashtable;
+import java.util.logging.Logger;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+
+import junit.framework.TestCase;
+
+import org.jnp.MissingObjectFactoryException;
+import org.jnp.server.SingletonNamingServer;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Ensures that requests to {@link Context#lookup(Name)}
+ * where the stored value is a {@link Reference} pointing to
+ * an unknown {@link ObjectFactory} result in a reliable
+ * and informative exception
+ * 
+ * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class MissingObjectFactoryBindingTestCase
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(MissingObjectFactoryBindingTestCase.class.getName());
+
+   /**
+    * Naming Context for bind/lookup
+    */
+   private static Context namingContext;
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   //-------------------------------------------------------------------------------------||
+   // Lifecycle --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Creates the new server
+    */
+   @BeforeClass
+   public static void createServerAndNamingContext() throws Exception
+   {
+      // Start the naming server
+      new SingletonNamingServer();
+
+      // Create a naming context
+      namingContext = new InitialContext();
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Tests ------------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Control; ensures that we can bind into JNDI and 
+    * look up a value via an {@link ObjectFactory}
+    */
+   @Test
+   public void testControl() throws NamingException
+   {
+      // Define a bind name
+      final String name = "/control";
+
+      // Bind an object factory into JNDI
+      final String factoryClassName = ContractedValueObjectFactory.class.getName();
+      this.bindObjectFactory(name, factoryClassName);
+
+      // Look up 
+      final Object obj = namingContext.lookup(name);
+
+      // Test expected value
+      final String expectedValue = ContractedValueObjectFactory.VALUE;
+      TestCase.assertEquals("Object from JNDI at \"" + name + "\" was not expected", expectedValue, obj);
+   }
+
+   /**
+    * Ensures that calls to lookup a
+    * @link Reference} pointing to
+    * an unknown {@link ObjectFactory} result in a reliable
+    * and informative exception
+    */
+   @Test(expected = MissingObjectFactoryException.class)
+   public void testExpectedExceptionOnMissingObjectFactory() throws NamingException
+   {
+      // Define a bind name
+      final String name = "/missingObjectFactory";
+
+      // Bind a missing object factory into JNDI
+      final String factoryClassName = "org.jboss.MissingObjectFactory";
+      this.bindObjectFactory(name, factoryClassName);
+
+      // Look up 
+      try
+      {
+         namingContext.lookup(name);
+      }
+      // Expected
+      catch (final MissingObjectFactoryException mofe)
+      {
+         // Just log
+         log.info(mofe.toString());
+         throw mofe;
+      }
+
+      // If we've reached here, no good, we should have gotten an exception
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods ------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Binds an {@link ObjectFactory} with the specified class name into JNDI at the specified
+    * location
+    */
+   private void bindObjectFactory(final String location, final String factoryClassName) throws NamingException
+   {
+      final Reference ref = new Reference(String.class.getName(), factoryClassName, null); // Expected type not important
+      namingContext.bind(location, ref);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Classes ------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * {@link ObjectFactory} implementation to always return the 
+    * same contracted value of {@link ContractedValueObjectFactory#VALUE}
+    */
+   public static class ContractedValueObjectFactory implements ObjectFactory
+   {
+
+      /**
+       * Value which will be returned for every lookup
+       */
+      static final String VALUE = "ExpectedValue";
+
+      /**
+       * {@inheritDoc}
+       * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable)
+       */
+      public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)
+            throws Exception
+      {
+         return VALUE;
+      }
+
+   }
+}
Index: jnpserver/src/main/java/org/jnp/interfaces/NamingContext.java
===================================================================
--- jnpserver/src/main/java/org/jnp/interfaces/NamingContext.java	(revision 97516)
+++ jnpserver/src/main/java/org/jnp/interfaces/NamingContext.java	(working copy)
@@ -75,6 +75,7 @@
 import javax.net.SocketFactory;
 
 import org.jboss.logging.Logger;
+import org.jnp.MissingObjectFactoryException;
 
 /**
  * This class provides the jnp provider Context implementation. It is a Context
@@ -1503,7 +1504,13 @@
    {
       if (useAbsoluteName(env))
          name = getAbsoluteName(name);
-      return NamingManager.getObjectInstance(obj, name, this, env);
+      final Object obtained = NamingManager.getObjectInstance(obj, name, this, env);
+      if(obtained instanceof Reference)
+      {
+         final Reference ref = (Reference) obtained;
+         throw MissingObjectFactoryException.create(ref.getFactoryClassName(), name);
+      }
+      return obtained;
    }
 
    /**
Index: jnpserver/src/main/java/org/jnp/MissingObjectFactoryException.java
===================================================================
--- jnpserver/src/main/java/org/jnp/MissingObjectFactoryException.java	(revision 0)
+++ jnpserver/src/main/java/org/jnp/MissingObjectFactoryException.java	(revision 0)
@@ -0,0 +1,111 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jnp;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+
+/**
+ * Indicates that a client has looked up a {@link Reference}
+ * pointing to an {@link ObjectFactory} that is not available 
+ * on the classpath or cannot otherwise be found.
+ * 
+ * JBNAME-42
+ * 
+ * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class MissingObjectFactoryException extends NamingException
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * serialVersionUID
+    */
+   private static final long serialVersionUID = 1L;
+
+   /*
+    * Strings used in generating the error message; hold the static parts here for better performance 
+    * and reduced String instance creation
+    */
+   private static final String ERROR_MESSAGE_PREFIX;
+
+   private static final String ERROR_MESSAGE_SUFFIX;
+
+   static
+   {
+      ERROR_MESSAGE_PREFIX = "Could not obtain " + ObjectFactory.class.getName()
+            + " implementation referenced from JNDI at \"";
+      ERROR_MESSAGE_SUFFIX = "\"; perhaps missing from the ClassPath?: ";
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Creates a new instance with the specified explanation;
+    * internal only, use {@link MissingObjectFactoryException#create(String, Name)}
+    * from the outside
+    * @param explanation
+    */
+   private MissingObjectFactoryException(final String explanation)
+   {
+      super(explanation);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Public Factory Methods -------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Creates a new instance explaining the error with the
+    * specified context
+    * 
+    * @param missingObjectFactoryClassName The name of the Class that could not be found
+    * @param targetName The JNDI target requested
+    * @throws IllegalArgumentException If either the missingObj
+    */
+   public static MissingObjectFactoryException create(final String missingObjectFactoryClassName, final Name targetName)
+         throws IllegalArgumentException
+   {
+      // Precondition checks
+      if (missingObjectFactoryClassName == null || missingObjectFactoryClassName.length() == 0)
+      {
+         throw new IllegalArgumentException("missing object factory class name is required");
+      }
+      if (targetName == null)
+      {
+         throw new IllegalArgumentException("target name is required");
+      }
+
+      // Construct the message
+      final StringBuilder sb = new StringBuilder();
+      sb.append(ERROR_MESSAGE_PREFIX);
+      sb.append(targetName);
+      sb.append(ERROR_MESSAGE_SUFFIX);
+      sb.append(missingObjectFactoryClassName);
+
+      // Create and return a new Exception
+      return new MissingObjectFactoryException(sb.toString());
+   }
+}
