Shows how to configure an ItsNat web project with Spring.
The Spring DI tricks used can be applied to other similar problems.
This is a translation, the original presentation is in Spanish.
3. THE PROBLEM
• Spring was born as a tool to configure and
integrate disparate technologies
• We can not always expect such disparate
technologies be ready to be configured “out of
the box” with Spring
This is the thing Spring was invented for!
3
4. THE PROBLEM
• ItsNat is a Java web framework
with a custom non-Spring configuration system
• ItsNat configuration is the most powerful and
flexible approach ever invented: Calling methods!
• As of day 0 ItsNat configuration was conceived to
be “overloaded” with higher level configuration
techniques and APIs, for instance… Spring!
4
8. BUT WE MUST KNOW HOW TO
CONFIGURE A WEB PROJECT BASED
ON ItsNat TO CONFIGURE IT LATER
WITH Spring
We will pick the “core” example in the
ItsNat Reference Manual
8
9. “PURE” ItsNat EXAMPLE: the servlet
• ItsNat does not define a concrete servlet,
developer must create one (or more)
– Configuration is done in method init
• In this example most of configuration is optional, just
used to show ItsNat configuration options
public class servlet extends HttpServletWrapper
{
public void init(ServletConfig config) throws ServletException
{
super.init(config);
ItsNatHttpServlet itsNatServlet = getItsNatHttpServlet();
ItsNatServletConfig itsNatConfig =
itsNatServlet.getItsNatServletConfig();
ItsNatServletContext itsNatCtx =
itsNatConfig.getItsNatServletContext();
9
10. “PURE” ItsNat EXAMPLE: the servlet
• ItsNatHttpServlet, ItsNatServletConfig
y ItsNatServletContext are the roots (and
singletons) of ItsNat configuration
itsNatCtx.setMaxOpenDocumentsBySession(6);
String serverInfo = getServletContext().getServerInfo();
boolean gaeEnabled = serverInfo.startsWith(
"Google App Engine");
itsNatCtx.setSessionReplicationCapable(gaeEnabled);
itsNatCtx.setSessionSerializeCompressed(false);
itsNatCtx.setSessionExplicitSerialize(false);
10
13. “PURE” ItsNat EXAMPLE: the servlet
• Now we register in the servlet an ItsNat template
core_example.xhtml and associated document loader
CoreExampleLoadListener
– Just a simple example of HTML page with AJAX
String pathPrefix = getServletContext().getRealPath("/");
pathPrefix += "/WEB-INF/pages/manual/";
ItsNatDocumentTemplate docTemplate;
docTemplate = itsNatServlet.registerItsNatDocumentTemplate(
"manual.core.example","text/html",
pathPrefix + "core_example.xhtml");
docTemplate.addItsNatServletRequestListener(
new CoreExampleLoadListener());
13
14. “PURE” ItsNat EXAMPLE: the servlet
• Another example, in this case a page with XML
docTemplate = itsNatServlet.registerItsNatDocumentTemplate(
"manual.core.xmlExample","text/xml",
pathPrefix + "xml_example.xml");
docTemplate.addItsNatServletRequestListener(
new CoreXMLExampleLoadListener());
• This XML example inserts an ItsNat “template
fragment”
– Template fragments have not “loaders/processors”
ItsNatDocFragmentTemplate docFragTemplate;
docFragTemplate = itsNatServlet.registerItsNatDocFragmentTemplate(
"manual.core.xmlFragExample","text/xml",
pathPrefix + "xml_fragment_example.xml");
14
16. “PURE” ItsNat EXAMPLE
• CoreExampleLoadListener is just a simple
launcher of document processors, called per page
loaded
public class CoreExampleLoadListener
implements ItsNatServletRequestListener
{
public CoreExampleLoadListener() {}
public void processRequest(ItsNatServletRequest request,
ItsNatServletResponse response)
{
ItsNatHTMLDocument itsNatDoc =
(ItsNatHTMLDocument)request.getItsNatDocument();
new CoreExampleDocument(itsNatDoc);
}
}
16
17. “PURE” ItsNat EXAMPLE
• CoreExampleDocument manages the page
(document) state receiving AJAX events
public class CoreExampleDocument implements EventListener
{
protected ItsNatHTMLDocument itsNatDoc;
protected Element clickElem1;
protected Element clickElem2;
public CoreExampleDocument(ItsNatHTMLDocument itsNatDoc)
{
this.itsNatDoc = itsNatDoc;
load();
}
...
17
21. “PURE” ItsNat EXAMPLE
• CoreXMLExampleLoadListener : in this case
(XML page) there is no AJAX events, we do not need a
class wrapping the document. This example includes the
template fragment "manual.core.xmlFragExample"
public class CoreXMLExampleLoadListener
implements ItsNatServletRequestListener
{
public CoreXMLExampleLoadListener() { }
public void processRequest(ItsNatServletRequest request,
ItsNatServletResponse response)
{
ItsNatDocument itsNatDoc = request.getItsNatDocument();
Document doc = itsNatDoc.getDocument();
Element discsElem = doc.getDocumentElement();
...
21
24. OBJETIVES
1. Build a single reused generic servlet :
itsnatspring.itsnatservlet
2. Configuration is fully done in a XML
configuration file of Spring in classpath:
itsnatex/spring.xml
3. The only user defined Java classes will be the
document wrappers/containers:
itsnatex.CoreExampleDocument
itsnatex.CoreXMLExampleDocument
24
25. CONSEQUENCES
• Besides the generic servlet we will need some
utility classes also generic and reusable for
other ItsNat+Spring projects
• These classes are not completed, just to cover
the needs of this example
– ItsNat has more configuration options
25
26. THE SERVLET
package itsnatspring;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import org.itsnat.core.http.HttpServletWrapper;
import org.itsnat.core.http.ItsNatHttpServlet;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
public class itsnatservlet extends HttpServletWrapper
{
public void init(ServletConfig config) throws ServletException
{
super.init(config);
ItsNatHttpServlet itsNatServlet = getItsNatHttpServlet();
GenericApplicationContext rootContext = new GenericApplicationContext();
ItsNatBeansRegistryUtil.registerSingletons(rootContext, itsNatServlet);
rootContext.refresh();
26
27. THE SERVLET
String springXMLPath = config.getInitParameter("spring_config");
if (springXMLPath == null)
throw new RuntimeException("spring_config initialization
parameter is not specified in web.xml");
ApplicationContext context =
new ClassPathXmlApplicationContext(
new String[] {springXMLPath},rootContext);
}
}
• ItsNat configuration objects are registered into a
generic ApplicationContext (the root), our
XML with Spring configuration is loaded by
another (child) Spring context
27
28. ItsNatBeansRegistryUtil
package itsnatspring;
import org.itsnat.core.ItsNatServletConfig;
import org.itsnat.core.ItsNatServletContext;
import org.itsnat.core.http.ItsNatHttpServlet;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class ItsNatBeansRegistryUtil
{
public final static String itsNatHttpServletBean = "itsNatHttpServlet";
public final static String itsNatServletConfigBean = "itsNatServletConfig";
public final static String itsNatServletContextBean = "itsNatServletContext";
public static ItsNatHttpServlet getItsNatHttpServlet(ApplicationContext context) {
return context.getBean(itsNatHttpServletBean,ItsNatHttpServlet.class);
}
public static ItsNatServletConfig getItsNatServletConfig(ApplicationContext context){
return context.getBean(itsNatServletConfigBean,ItsNatServletConfig.class);
}
public static ItsNatServletContext getItsNatServletContext(ApplicationContext context){
return context.getBean(itsNatServletContextBean,ItsNatServletContext.class);
}
28
29. ItsNatBeansRegistryUtil
public static void registerSingletons(AbstractApplicationContext context,
ItsNatHttpServlet itsNatServlet)
{
ItsNatServletConfig itsNatServletCofig =
itsNatServlet.getItsNatServletConfig();
ItsNatServletContext itsNatServletContext =
itsNatServletCofig.getItsNatServletContext();
ConfigurableListableBeanFactory beanFact = context.getBeanFactory();
beanFact.registerSingleton(itsNatHttpServletBean,itsNatServlet);
beanFact.registerSingleton(itsNatServletConfigBean,itsNatServletCofig);
beanFact.registerSingleton(itsNatServletContextBean,itsNatServletContext);
}
}
• ItsNat configuration objects are manually
registered as singletons in Spring context
29
32. ItsNatServletContextBean
• This utility class is used as a singleton to save the
specified flags and in the end of bean configuration
they are registered calling methods of
ItsNatServletContext
– Because we need the ApplicationContext
we will implement
ApplicationContextAware
– Because we must to save in ItsNat context our
configuration data in the end of bean
configuration we need to implement
InitializingBean
32
37. LocaleBean
• This “factory bean” allows configuring a Locale and
made public calling the “factory method”
getLocale()
package itsnatspring;
import java.util.Locale;
import org.springframework.beans.factory.InitializingBean;
public class LocaleBean implements InitializingBean
{
protected String language;
protected String country;
protected Locale locale;
public LocaleBean() { }
public String getCountry() { return country; }
public void setCountry(String country) { this.country = country; }
public String getLanguage() { return language; }
37
38. LocaleBean
public void setLanguage(String language) { this.language = language; }
public Locale getLocale() { return locale; }
@Override
public void afterPropertiesSet() throws Exception
{
Locale[] availablelocales = Locale.getAvailableLocales();
for(Locale locale : availablelocales)
if (locale.getLanguage().equals(language) &&
locale.getCountry().equals(country))
{
this.locale = locale;
return;
}
this.locale = new Locale(language,country);
}
}
38
39. • Some other utility classes are very similar to the
previous shown, from now we are just to show
only the most interesting
• From Spring XML you can figure out how they
work under the hood
– ItsNat singletons are got through
ItsNatBeansRegistryUtil and the Spring
ApplicationContext
– This context is got implementing
ApplicationContextAware
39
42. ItsNatServletRequestListenerBean
• This “local singleton bean” is very interesting becase it works
like a generic “ItsNat document loader listener”
implementing ItsNatServletRequestListener
• To be generic we must invent a simple interface
ItsNatDocumentInitialize for the document
processors/wrappers:
package itsnatspring;
import org.itsnat.core.ItsNatServletRequest;
import org.itsnat.core.ItsNatServletResponse;
public interface ItsNatDocumentInitialize
{
public void load(ItsNatServletRequest request,
ItsNatServletResponse response);
}
42