2001: JNDI Its all in the Context

634 views
534 views

Published on

Back in 2001 I was giving talks on how to use Java Naming and Directory Interface effectively.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
634
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
15
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

2001: JNDI Its all in the Context

  1. 1. 1 Copyright 2000 SyncTank Solutions, Inc. JNDI, It’s All in the Context Russell Castagnaro Chief Mentor 4Charity.com russell@4charity.com Copyright 2000 SyncTank Solutions, Inc. Introduction • Presenter – Russell Castagnaro – Chief Mentor • 4Charity.com • SyncTank Solutions, Inc – russell@4charity.com – Experience
  2. 2. 2 Copyright 2000 SyncTank Solutions, Inc. Introduction • 4Charity.com – Application Service Provider for the Non- Profit industry – Pure Java development – Http://www.4charity.com – Locations: • San Francisco,CA • Honolulu, HI – We’re Hiring… Copyright 2000 SyncTank Solutions, Inc. Why JNDI? You can: • Develop networked application. • Find remote objects. • Interface with distributed systems. • Interact with non-Java, networked systems
  3. 3. 3 Copyright 2000 SyncTank Solutions, Inc. Presentation Goals • Review of basic JNDI. • Using JNDI for local service resolution. • JNDI as an alternative to static constants. • Using Custom Contexts with JNDI. • Implementing Singletons. • Using RMI and IIOP. • Using Events in JNDI. Copyright 2000 SyncTank Solutions, Inc. Who needs JNDI? • If you want to use J2EE, you need JNDI. • JNDI is the standard way to access distributed and local resources for enterprise applications.
  4. 4. 4 Copyright 2000 SyncTank Solutions, Inc. What is JNDI? • JNDI is a set of interfaces. • Provides a programming interface, allowing for Discovery and Registration. • Standards-based approach, providing common API to a searchable structure of objects. • Naming Services • Directory Services Copyright 2000 SyncTank Solutions, Inc. What is a Naming Service? • Provides the ability to map a name or identifier to objects or services. • A tree-like structure, nodes can be associated with other nodes or objects. • Objects are bound into the JNDI tree. • Objects can be resolved by performing a lookup using the composite name.
  5. 5. 5 Copyright 2000 SyncTank Solutions, Inc. Naming JNDI Tree lives in the Server as a collection of Named Object References Object/ Service Reference Copyright 2000 SyncTank Solutions, Inc. What is a Directory Service? • Provides a structure containing objects. • Allows access to object attributes. • Enables searching the structure using these attributes. • Think of a computer’s file system or an SQL database. • Simple JNDI has one attribute, the object’s name.
  6. 6. 6 Copyright 2000 SyncTank Solutions, Inc. JNDI is Like a Database • Start with a database instance. • Use a tablespace or ownership area. • Access a table in the tablespace. • Access a row in the table. • Access a column in the row. sqlplus scott@beq-local “SELECT name FROM scott.emp;” Copyright 2000 SyncTank Solutions, Inc. JNDI is Like a File System • Start with a mounted drive. • Use a subdirectory. • Access a subdirectory. • Access a file. “C:/data/your_client/financials.xls”
  7. 7. 7 Copyright 2000 SyncTank Solutions, Inc. Using JNDI • Start with an Initial Context. • Navigate to a Sub-Context. • Drill-down through other sub-contexts. • Access the object or service. new InitialContext().lookup(“name”); Copyright 2000 SyncTank Solutions, Inc. Comparisons JNDI File System RDBMS Initial Context Mount Point (c:) Database instance SubContext Subdirectory Tablespace SubContext Subdirectory Table Object File Data (row) rmi://myserver:8080 /myobjects.example .object c:datayour_clie ntfinancials.xls SELECT * FROM Demo.Employee
  8. 8. 8 Copyright 2000 SyncTank Solutions, Inc. JNDI Example package com.synctank.labs.jndi; import javax.naming.*; public class TestJNDI { public static void main(String _arg[]){ Object o = null; InitialContext ctx= null; try{ ctx = new InitialContext(System.getProperties()); o = ctx.lookup("myobjects.example.object"); String s = (String)o; System.out.println("Found a string: "+s); } catch (ClassCastException e) { System.out.println("Found a "+o.getClass().getName() +": "+o.toString() ); } catch (NamingException ne) { System.out.println("We have a problem!"); ne.printStackTrace(); } finally { try { ctx.close(); }catch (Exception e ) {} } } } Copyright 2000 SyncTank Solutions, Inc. JNDI Example • Primary classes are located in the javax.naming package. • Primarily use Context objects: – javax.naming.Context – javax.naming.InitialContext – javax.naming.directory.InitialDirContext – javax.naming.ldap.InitialLdapContext • Use a context that matches your needs.
  9. 9. 9 Copyright 2000 SyncTank Solutions, Inc. JNDI Providers • JNDI Providers are the services that will be accessed. • More on the Service Provider Interface Later. • Most application servers come with some Naming service. • J2SDK v. 1.3 includes code for many interfaces. • Many are downloadable, for free, at http://java.sun.com/products/jndi/serviceproviders.html#12 Copyright 2000 SyncTank Solutions, Inc. Starting the Service • FS service doesn’t need to be started! • RMI Registry (JNDI Service) – start rmiregistry.exe OR – java.rmi.registry.LocateRegistry.createRegistry(port); • Weblogic JNDI service – start startWebLogic.cmd OR – ./startWebLogic.sh &
  10. 10. 10 Copyright 2000 SyncTank Solutions, Inc. Getting the Initial Context • Similar to JDBC. Use a Hashtable object. • Two required properties: – Context.INITIAL_CONTEXT_FACTORY – Context.PROVIDER_URL • Other optional properties: – Context.SECURITY_PRINCIPAL – Context.SECURITY_CREDENTIALS – And many, many more.. Copyright 2000 SyncTank Solutions, Inc. Getting the Initial Context • Context.INITIAL_CONTEXT_FACTORY – Actually “java.naming.factory.initial” – Name of the Factory that creates Initial Contexts. • Context.PROVIDER_URL – Actually “java.naming.provider.url” – Tells JNDI where to find the service. • Context.SECURITY_PRINCIPAL – Who is the connecting? • Context.SECURITY_CREDENTIALS – What is authentication object (password, certificate,..)
  11. 11. 11 Copyright 2000 SyncTank Solutions, Inc. Getting the Initial Context • Place the correct properties in a Hashtable or Properties object. • Call the constructor for the InitialContext class, pass the Hashtable as a parameter. • Catch (throw) any Naming Exceptions! • Remember to close() the context when done. Copyright 2000 SyncTank Solutions, Inc. Getting the Initial Context public static InitialContext getInitialContext() throws NamingException { // use the factory and url supported by your provider String factory = "weblogic.jndi.WLInitialContextFactory"; String url = "t3://localhost:7001"; // “http://localhost:7001”; String user = null; String password = null; java.util.Hashtable p = new java.util.Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, factory); p.put(Context.PROVIDER_URL, url); if (user != null && password != null ) { p.put(Context.SECURITY_PRINCIPAL, user); p.put(Context.SECURITY_CREDENTIALS, password); } return new InitialContext(p); }
  12. 12. 12 Copyright 2000 SyncTank Solutions, Inc. Getting the Initial Context (file system) public static void main(String[] args) { Hashtable env = new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); String root = "file:/jdk1.3"; if (args != null && args.length > 0) root = args[0]; env.put(Context.PROVIDER_URL, "file:/jdk1.3"); try { Context ctx = new InitialContext(env); String start = ""; if (args != null && args.length > 0) start = args[0]; listBindings(ctx,start); ctx.close(); } catch (NamingException e) { System.out.println("List Bindings failed: " + e); } } Copyright 2000 SyncTank Solutions, Inc. EJSkin Lookup Properties p = new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, “com.ejskin.context.SkinnyInitialContextFactory" ); p.put(Context.PROVIDER_URL, “ejs://ejs.ejs.com:666"); Context ctx = new InitialContext(p); SkinnyAppp app = (SkinnyApp)ctx.lookup(“SkinyApp.fore”);
  13. 13. 13 Copyright 2000 SyncTank Solutions, Inc. Resolving Objects • Once you have a context any lookup is a relative search. • user.russell.castagnaro.wallet can be resolved from: – The initial context as ctx.lookup(“user.russell.castagnaro.wallet”); – A subcontext “user.russell” as ctx.lookup(“castagnaro.wallet”); • Access a sub-context using the lookup method from any context. Context ctx = new InitialContext(p); Context sub = ctx.lookup("user"); sub = sub.lookup("russell"); sub = sub.lookup(”castagnaro"); Object o = sub.lookup("wallet"); Copyright 2000 SyncTank Solutions, Inc. JNDI Perusal • It is possible to dynamically access all of the objects bound into the JNDI tree with two overloaded methods: – public abstract NamingEnumeration list(java.lang.String) throws NamingException; – public abstract NamingEnumeration list(javax.naming.Name) throws NamingException; – public abstract NamingEnumeration listBindings(java.lang.String) throws NamingException; – public abstract NamingEnumeration listBindings(javax.naming.Name) throws NamingException; • There is a very large difference between the two methods!
  14. 14. 14 Copyright 2000 SyncTank Solutions, Inc. JNDI Perusal • listBindings() – Returns an enumeration of Binding objects. – Bindings contain the actual object* from the tree! – May take a long time! • list() – Returns an Enumeration of NameClassPair objects. – Access to the Name and class, but not the object. – Faster than the alternative, like a ‘shallow get.’ * Remote objects are an exception. Copyright 2000 SyncTank Solutions, Inc. JNDI Perusal Example Code public static void list(Context ctx,StringBuffer sb) { try { NamingEnumeration enum = ctx.listBindings(""); while (enum.hasMore()) { Binding binding = (Binding)enum.next(); Object obj = (Object)binding.getObject(); if (obj instanceof Context) { sb.append("---> "); sb.append(binding.getName()); sb.append("."); list((Context)obj,_sb); } else {sb.append(binding.getName()); sb.append("n"); } } } catch (NamingException e) { System.out.println(e); } }
  15. 15. 15 Copyright 2000 SyncTank Solutions, Inc. JNDI Perusal Output ---> javax.---> jts.UserTransaction ---> transaction.UserTransaction ---> jms.QueueConnectionFactory TopicConnectionFactory PrePackagedSessionEJB_EO ---> weblogic. ---> fileSystem. ---> ejb.EJBManager ---> common.T3Services ---> jdbc.JdbcServices ---> connectionPool.ejbpool cs1 demoPool cs ---> jts.CoordinatorFactory[] CoordinatorFactory ---> server.myserver WebLogic ---> rmi.---> jms.ServerSessionPoolFactory ---> jndi. ---> internal.RemoteContextFactor y RemoteContextFactory Copyright 2000 SyncTank Solutions, Inc. Adding Objects • You can use the bind() or rebind() methods to add objects to the tree. • If an object extends java.io.Serializable, it is copied and placed into the tree. • If an object extends java.rmi.Remote, a copy of the stub is placed into the tree. • rebind() will automatically overwrite an existing object. • bind() throws a javax.naming.NamingException
  16. 16. 16 Copyright 2000 SyncTank Solutions, Inc. Adding Objects public static void main(String args[]) throws java.rmi.RemoteException{ Hashtable ht = new Hashtable(); ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); ht.put(Context.PROVIDER_URL, "t3://localhost:7001"); try { Context ic = new InitialContext(ht); //serializable, an actual copy put into the tree ic.bind("Object1",new String("Object1")); ic = ic.createSubContext(“foo”); //remote, a copy of the stub placed in the tree ic.bind("Trivial",new TrivialImpl("Trivial!")); } catch (NamingException e){ System.out.println(e.getMessage()); } } Copyright 2000 SyncTank Solutions, Inc. Other Features • Use unbind() to remove an object from the tree. • Use rename() to change its registered name. • Use custom startup classes to bind objects into the tree upon start up. • Use custom properties to automatically bind objects into the tree.
  17. 17. 17 Copyright 2000 SyncTank Solutions, Inc. Other Features • Removing Items from the JNDI Tree try { Context ic = new InitialContext(ht); ic.unbind(data); System.out.println(data+ " successfully unbound."); } catch (NamingException e) .. • Renaming try { Context ic = new InitialContext(ht); ic.rename(oldName, newName); } catch (NamingException e) .. Copyright 2000 SyncTank Solutions, Inc. Local Data Access • Accessing local data using constants requires recompilation to change those values public static String SOME_VALUE=“foo”; • Using JNDI gives you the freedom to pin values that need to be shared, without access to: – System properties – File Systems – Custom Classes
  18. 18. 18 Copyright 2000 SyncTank Solutions, Inc. Local Data Access • Enterprise Java Beans require the use of this JNDI for deployment values. • Allows deployment specialists to change values without recompilation. • EJB deployment descriptor snippet: <env-entry> <env-entry-name>foo</env-entry-name> <env-entry-type>String</env-entry-type> <env-entry-value>bar</env-entry-value> </env-entry> Copyright 2000 SyncTank Solutions, Inc. Local Data Access • Use a local context and lookup the object by prepending “java:comp/env” ctx = new InitialContext(); String foo = (String)ctx.lookup(“java:comp/env.foo”);
  19. 19. 19 Copyright 2000 SyncTank Solutions, Inc. Using Custom Startup Classes • Using a custom WebLogic startup Class public String startup(String _name, java.util.Hashtable _args) throws Exception { TrivialImpl o = new TrivialImpl(); System.out.println("TrivialImpl instanciated.."); Context context = getInitialContext(); context.rebind(_name, o); System.out.println("Bound.."); return ("TrivialImpl bound to the name "+_name); } public void setServices(weblogic.common.T3ServicesDef services){} Copyright 2000 SyncTank Solutions, Inc. Using a Startup Servlet public void init(ServletConfig config) throws ServletException { super.init(config); String className = config.getInitParameter("CLASS_NAME"); String jndiName = config.getInitParameter("JNDI_NAME"); if (className != null && jndiName != null) { try{ Object o = Class.forName(className).newInstance(); Context ctx = new InitialContext(); ctx.rebind(jndiName,o); log("StartupServlet has bound "+ className +" into”+ the JNDI tree as "+ jndiName); } catch (Exception ne) { throw new ServletException(ne); } }
  20. 20. 20 Copyright 2000 SyncTank Solutions, Inc. Singletons • You need one and only one instance of a particular class. • You want to provide access to distributed applications/ services. • Don’t make static methods! Make the class an RMI object. • Bind the object’s implementation into the JNDI tree. • Essentially what happens for EJBHome interfaces. Copyright 2000 SyncTank Solutions, Inc. CORBA Objects • When accessing CORBA objects, things used to be more complicated. • RMI over IIOP, included in Java 2, solves this problem. • Narrowing the object maps it from a CORBA object to a Java object auto- magically.
  21. 21. 21 Copyright 2000 SyncTank Solutions, Inc. Narrowing • If you access services using RMI over IIOP (WebSphere, Iona, etc.). • If you use HomeHandle or Handle objects (EJB 1.1). • Use PortableObject.narrow() • Pass an Object and the class you expect from the remote method call. Copyright 2000 SyncTank Solutions, Inc. Class Narrowing ObjectOutputStream stream = ...; Account account = ...; Handle handle = account.getHandle(); stream.writeObject(handle); // A client can read the handle from stable storage, and use the // handle to resurrect an object reference to the // account entity object. // ObjectInputStream stream = ...; Handle handle = (Handle) stream.readObject(handle); Account account = (Account)javax.rmi.PortableRemoteObject.narrow( handle.getEJBObject(), Account.class); account.debit(100.00);
  22. 22. 22 Copyright 2000 SyncTank Solutions, Inc. JDBC and JNDI • It is possible to use JNDI to store JDBC connection objects: SampleDataSource sds = new SampleDataSource(); sds.setServerName(“BEQ-LOCAL”); sds.setDatabaseName(“demo”); Context ctx = new InitialContext(); ctx.bind(“EmployeeDB”, sds); • Application servers typically feature datasource publishing: weblogic.jdbc.TXDataSource.ejbDataSource=ejbPool weblogic.jdbc.DataSource.ejbPool=ejbPool Copyright 2000 SyncTank Solutions, Inc. JDBC and JNDI • Use them later to avoid prior knowledge of driver information: Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup(“ejbDataSource”); Connection con = ds.getConnection();
  23. 23. 23 Copyright 2000 SyncTank Solutions, Inc. Events • JNDI Events provide local or remote callback functionality. • Similar to the event model used in Swing. • Uses subclasses of the javax.naming.NamingListener interface. • NamingListeners: – NamespaceChangeListener – ObjectChangeListener – UnsolicitedNotificationListener Copyright 2000 SyncTank Solutions, Inc. Events • JNDI Events require the use of a different type of context. • New Context interfaces: – EventContext for standard naming services – EventDirContext for LDAP service • Access Contexts in a familiar way: EventDirContext edc = (EventDirContext) (new InitialDirContext(env).lookup("ou=People"));
  24. 24. 24 Copyright 2000 SyncTank Solutions, Inc. JNDI Gotchas • Use rebind() wisely. • Know the URL and InitialContextFactory class name. • When using advanced features (LDAP, etc.) place the correct resources in your classpath. .librmiregistry.jar;.libproviderutil.jar; .libjndi.jar;.libjaas.jar;.libldap.jar; .libldapbp.jar;.libfscontext.jar • J2EE has made deploying JNDI services much easier, look for vendors to support advanced features 2Q 2000. Copyright 2000 SyncTank Solutions, Inc. Review • JNDI is used for all advanced J2EE features. • JNDI provides an easy method of accessing remote or local resources. • Use bind() or rebind() to register objects. • Use lookup() to resolve objects. • Use your server vendors startup facilities for initial JNDI registration.
  25. 25. 25 Copyright 2000 SyncTank Solutions, Inc. Finally • Thanks for attending. • Live in Hawaii or Bay Area? Do you like this stuff? Email your resume to us! • Source Code Available: – http://www.synctank.com/softwaresummit – russell@4charity.com • Aloha!

×