[wiki] Updated: IocContainerInternals/TheBasics/CommonPatterns

[email protected]
Newsgroups gmane.comp.java.jicarilla.cvs
Message-ID <[email protected]>
   Date: 2004-03-16T17:44:43
   Editor: 130.89.169.128 <>
   Wiki: JicarillaWiki
   Page: http://lsd.student.utwente.nl/jicarilla/IocContainerInternals_2fTheBasics_2fCommonPatterns

   no comment

Change Log:

------------------------------------------------------------------------------
@@ -8,26 +8,118 @@
 
 == Component type assumptions ==
 
-''TODO''
- * some kind of spec. Explain how assumptions like only dealing with...
-   * javabean
-   * avalon component
-   * dependency injection
-   * servlet
-   * JMX aware
-   * JNDI aware
-   * ...
+Remember the factory interface?
+
+{{{
+public interface Factory 
+{ 
+  Object newInstance(); 
+}
+}}}
+
+I showed a rather trivial implementation of this factory that wasn't very reusable earlier on. Here's a modified version:
+
+{{{
+class JButtonFactory implements Factory
+{ 
+  Object getInstance() 
+  { 
+    return new JButton(); 
+  } 
+} 
+}}}
+
+you can only use this for JButton instances. It would be quite boring to write such a factory for each and every component you use. We want to write a smart factory implementation once, so we can reuse it. How do we do that?
+
+=== Limitations on the constructor ===
+
+Well, a common strategy is to put some requirement on the component. Like:
+
+  '''Components must have a public no-argument constructor.'''
+
+We can create a factory that knows how to create any component that fulfills that contract. Something like...
+
+{{{
+class BasicFactory implements Factory
+{
+  Class classToCreateInstancesFrom;
+
+  BasicFactory( Class clazz )
+  {
+    classToCreateInstancesFrom = clazz;
+  }
+ 
+  Object getInstance()
+      throws Exception
+      // hey! Exception handling to figure out here!
+  { 
+    return classToCreateInstancesFrom.newInstance();
+  } 
+} 
+}}}
+
+note that the {{{Class.newInstance()}}} method throws all kinds of exceptions. To make this work, we'd need to add all kinds of assertions, validate arguments, wrap and unwrap exceptions, etc. Let's agree to ignore exception handling for now. Just remember that these code samples won't compile because they don't handle exceptions well.
+
+=== What about JavaBeans? ===
+
+Most real-life components don't work well with just a public no-argument constructor. Take javabeans as an example. Besides the constructor contract, they also have setXXX() methods which sometimes need to be called. The contract is a little like:
+
+  '''Components sometimes have {{{public void}}} methods whose names start with {{{set}}}, with the fourth letter being capital. These methods ''may'' need to be called before you can use the component, with ''appropriate'' arguments.'''
+
+This is quite a weak contract (what's with the "may" and the "appropriate"?), but its well-known and used a lot. The contract is usually made stronger for each and every individual component by specifying it in documentation and unit tests.
+
+Can we create a factory that can instantiate any javabean? Sure! Here's some sketchy code that shows the basics:
+
+{{{
+class BeanFactory implements Factory
+{
+  Class classToCreateInstancesFrom;
+  Resolver resolverToGetPropertiesFrom;
+
+  BasicFactory( Class clazz, Resolver resolver )
+  {
+    classToCreateInstancesFrom = clazz;
+    resolverToGetPropertiesFrom = resolver;
+  }
+ 
+  Object getInstance()
+  { 
+    Object instance = classToCreateInstancesFrom.newInstance();
+    
+    PropertyDescriptor[] properties = Introspector
+      .getBeanInfo( classToCreateInstancesFrom )
+      .getPropertyDescriptors();
+
+    for( property : properties )
+    {
+      String name = property.getName();
+      Method setMethodToCall = descriptor.getWriteMethod();
+      Object methodArgument = resolverToGetPropertiesFrom.get( name );
+      setMethodToCall.invoke( instance, new Object[] { methodArgument } );
+    }
+  } 
+} 
+}}}
+
+you can see us using the {{{javax.beans}}} package here, and some reflection magic. A robust and flexible bean factory has a lot more code to it than this, but you'll get the basic idea.
+
+=== Other kinds of components ===
 
- ...can simplify things.
+I picked the javabeans contract because its a well-known example of a component contract. There's many others. You'll hear people refer to dependency injection (in constructor and method variants), "type 1", "type 2" and "type 3" IoC, avalon-framework, XXXAware interfaces, and more. There's also JMX Beans, JNDI-querying beans, POJOs, EJBs, servlets, and more. It would be really boring to spend a lot of time talking about these contracts, their pros and cons. From the perspective of implementing a container, it's just a lot more of the same thing! You might imagine having a factory for javabeans, a factory for type 3 IoC components, a factory for servlets, etc etc. Rather boring bits of plumbing :-D
 
 == Caching limitations ==
 
-''TODO''
- * support subset of all possible caching setups. (move from previous page)
+I wrote down a big list of "caching setups" on the previous page. You could choose to have a system full of singleton-like objects, or you could create new objects every time one is needed, or something else alltogether.
+
+Most containers either support one type of caching. Contracts are often fairly rigid and simple. Stuff like:
+
+  ''A single instance of each component will live inside the container, and it will be shared between all the other objects in the system. The component probably needs to be thread safe and know how to handle multiple clients.''
+
+Other containers support a few types of caching. Their designers will take a good look at a particular set of problems, and will offer you only a few choices, that will work well for most solutions to those kinds of problems. Most frameworks designed for working inside a servlet engine are good examples. They'll offer a few types of caching, usually called "scopes". You can, for example, configure a component to be "shared" (between webapps), "singleton" (one component per webapp), or "per-session" (one per client session).
 
-   -- or --
+A third choice, which is currently a lot less common (but one I like myself :-D) is to support every kind of caching. The only way to feasibly do that without getting a very ugly and cluttered codebase, is to encapsulate the caching choice into a truly seperate concern (which it really seems to be) and create an abstraction for it. Besides containers, resolvers, and factories, we'll need to have a "Cacher" of some kind. It probably needs to sit somewhere between the container and the factory. A typical setup might result in things like
 
- * coding pattern to delegate caching setups elsewhere (helper or directly to the component)
+''TODO: image!''
 
 == Concept merging ==
 


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.