> -----Original Message-----
> From: Kristinn Danielsson [mailto:[EMAIL PROTECTED]
> Hi
>
> I have a Struts application and I want to use Merlin contained
> services in
> it.
> I saw something like MerlinServlet in the avalon CVS. Would this be
> appropriate start for my investigation? If so can someone tell me how I
> can access the Merlin contained services from my Struts Actions?
I cannot comment on Struts as I never used it. I recently ported a small app
of mine which uses WebWork2, another MVC framework, to Merlin. Like Struts,
WW2 uses a central controller servlet which dispatches request to
preconfigured action classes. What I did was the following:
- Had a look at the MerlinServlet. In its init() method it created an
embedded Merlin kernel and stored it in the ServletContext (storage in the
servlet container's JNDI context would be a viable alternative).
- Subclassed WW2's controller servlet, overriding its init() method. Copied
behaviour from MerlinServlet (creating embedded Merlin kernel, storing it or
rather its root block - in ServletContext).
- Created an (abstract) action class derived from WW2's default action
class. This provided something like
protected Kernel getEmbeddedKernel()
{
Kernel kernel = (Kernel) servletContext.getAttribute(KERNEL_KEY);
return kernel;
}
(Actually, I went straight for the root block - acquireRootBlock() - but
you get the idea). This action class was to become the base class for all my
action classes.
>
> If this is completely wrong direction, please give me some hints.
No, it's the right direction. To make things clearer below you will find the
source for my controller servlet and my action class, edited to show the
relevant parts. As I said, I skipped the kernel proper and went straight for
the root block (Merlin's top level container). Adapt to your needs.
Hope this helps,
Olaf
----------------------------------------------------------------------------
----------------
(1) Servlet (All credits go to Stephen M. McConnell):
public class MerlinDispatcherServlet extends ServletDispatcher
{
//----------------------------------------------------------
// static
//----------------------------------------------------------
private static final String MERLIN_PROPERTIES = "merlin.properties";
private static final String IMPLEMENTATION_KEY = "merlin.implementation";
//--------------------------------------------------------------------------
// state
//--------------------------------------------------------------------------
private KernelCriteria m_criteria;
private Block m_block;
private Kernel m_kernel;
//--------------------------------------------------------------------------
// Servlet
//--------------------------------------------------------------------------
/**
* Initializes Servlet by the web server container.
*
* @exception ServletException if an error occurs
*/
public void init() throws ServletException
{
ClassLoader classloader = this.getClass().getClassLoader();
try
{
File base = getServletContextDirectory();
getServletContext().log(
"[MerlinDispatcherServlet] Using context directory: "
+ base);
File repository = getRepository();
getServletContext().log(
"[MerlinDispatcherServlet] Using repository: " +
repository);
String[] hosts =
new String[] {
"file:/C:/Data/OBergner/Maven/repository/",
"http://dpml.net/",
"http://www.ibiblio.org/maven/" };
InitialContext context =
new DefaultInitialContext(
base,
classloader,
null,
repository,
hosts);
Artifact artifact =
DefaultBuilder.createImplementationArtifact(
classloader,
null,
base,
MERLIN_PROPERTIES,
IMPLEMENTATION_KEY);
Builder builder = new DefaultBuilder(context, artifact);
Factory factory = builder.getFactory();
m_criteria = (KernelCriteria) factory.createDefaultCriteria();
m_criteria.put("merlin.server", "true");
m_criteria.put("merlin.info", "true");
m_criteria.put("merlin.debug", "true");
m_criteria.put("merlin.repository", repository);
//
// this is where we customize content based on web.xml
// (currently not implemented - lets see what we can do with
// with merlin.properties first of all)
//
m_kernel = (Kernel) factory.create(m_criteria);
getServletContext().setAttribute(
ContextKeys.ROOT_BLOCK_KEY,
m_kernel.getBlock());
getServletContext().log(
"[MerlinDispatcherServlet] Kernel established. "
+ "Root block stored in servlet context under
key: "
+ ContextKeys.ROOT_BLOCK_KEY);
}
catch (Throwable e)
{
final String error = ExceptionHelper.packException(e, true);
System.out.println(error);
throw new ServletException(error, e);
}
}
/**
* Disposes of container manager and container instance.
*/
public void destroy()
{
if (m_kernel != null)
{
System.out.println("tearing down");
try
{
m_kernel.shutdown();
}
catch (Throwable e)
{
final String error = "Runnable kernel shutdown
failure.";
final String msg =
ExceptionHelper.packException(error, e, true);
throw new RuntimeException(msg, null);
}
finally
{
m_kernel = null;
}
}
super.destroy();
}
//------------------------------------------------------------------------
// default values - might be overridden in subclasses
//------------------------------------------------------------------------
protected File getRepository()
{
return new File(getMavenLocalHome(), "repository");
}
protected String[] getHosts()
{
return new String[] {
"file:/C:/Data/OBergner/Maven/repository/",
"http://dpml.net/",
"http://www.ibiblio.org/maven/" };
}
protected String getOverridePath()
{
File base = getServletContextDirectory();
File config = new File(base, "WEB-INF/conf/override.xml");
if (config.exists())
return "conf/override.xml";
return null;
}
protected URL getKernelConfPath() throws Exception
{
return new File(
getServletContextDirectory(),
"WEB-INF/conf/kernel.xml")
.toURL();
}
protected String[] getDeploymentObjectives()
{
return new String[] {
getServletContextDirectory().getAbsolutePath()
+ "/target/classes" };
}
//----------------------------------------------------------------------
// utilities
//----------------------------------------------------------------------
private void applyConfiguration(final Map criteria) throws Exception
{
criteria.put("merlin.repository", getRepository());
criteria.put("merlin.context", "target");
criteria.put("merlin.server", "true");
criteria.put("merlin.info", "true");
criteria.put("merlin.debug", "true");
// The hardcoded deployment path takes precedence over the one
// specified in the merlin.properties file
String[] deployments = getDeploymentObjectives();
if (deployments.length == 0)
{
deployments = (String[]) criteria.get("merlin.deployment");
if (deployments.length == 0)
{
final String error = "Cannot locate a deployment
objective.";
throw new IllegalStateException(error);
}
}
criteria.put("merlin.deployment", deployments);
// The hardcoded kernel configuration path takes precedence over
// the one passed in via merlin.properties
URL kernelConf = getKernelConfPath();
if (kernelConf == null || kernelConf.equals(""))
{
kernelConf = (URL) criteria.get("merlin.kernel");
if (kernelConf == null || kernelConf.equals(""))
{
final String error = "Cannot locate kernel config.";
throw new IllegalStateException(error);
}
}
criteria.put("merlin.kernel", kernelConf);
// The hardcode override config path takes precedence over the one
// passed in via merlin.properties
if (getOverridePath() == null || getOverridePath().equals(""))
{
String override = (String) criteria.get("merlin.override");
if (null != override)
{
criteria.put("merlin.override", override);
}
}
}
/**
*
* @return The servlet's context directory.
*/
private File getServletContextDirectory()
{
final String path = getServletContext().getRealPath(".");
return new File(path);
}
private static File getMavenLocalHome()
{
try
{
String local =
System.getProperty(
"maven.home.local",
Env.getEnvVariable("MAVEN_HOME_LOCAL"));
if (null != local)
return new File(local).getCanonicalFile();
return new File("C:/Data/OBergner/Maven").getCanonicalFile();
}
catch (Throwable e)
{
final String error =
"Internal error while attempting to access
environment.";
final String message =
ExceptionHelper.packException(error, e, true);
throw new RuntimeException(message);
}
}
/**
* Return the merlin home directory.
* @return the merlin install directory
*/
private static File getMerlinHome()
{
return new File(getMerlinHomePath());
}
/**
* Return the merlin home directory path.
* @return the merlin install directory path
*/
private static String getMerlinHomePath()
{
try
{
String merlin =
System.getProperty(
"merlin.home",
Env.getEnvVariable("MERLIN_HOME"));
if (null != merlin)
return merlin;
return System.getProperty("user.home") + File.separator +
".merlin";
}
catch (Throwable e)
{
final String error =
"Internal error while attempting to access MERLIN_HOME
environment.";
final String message =
ExceptionHelper.packException(error, e, true);
throw new RuntimeException(message);
}
}
}
(2) Action:
public abstract class AbstractManPlanAction
extends ActionSupport
implements MessageProvider, ContextKeys, MessageKeys
{
...
//**************************************************************************
*
// Private instance fields
//**************************************************************************
*
...
private Block m_rootBlock;
...
//**************************************************************************
*
// Internal API
//**************************************************************************
*
protected UserManager userManager()
{
if (m_rootBlock == null)
{
acquireRootBlock();
}
try
{
return (UserManager) m_rootBlock
.locate(UserManager.LOOKUP_KEY)
.resolve();
}
catch (Exception e)
{
final String msg =
"Error while retrieving user-manager from "
+ "servlet context: "
+ e.getMessage();
log.error(msg, e);
throw new RuntimeException(msg, e);
}
}
...
//**************************************************************************
*
// Private utility methods
//**************************************************************************
*
private void acquireRootBlock()
{
m_rootBlock =
(Block) ServletActionContext.getServletContext().getAttribute(
ROOT_BLOCK_KEY);
if (m_rootBlock == null)
{
final String msg =
"Could not find root block under key '"
+ ROOT_BLOCK_KEY
+ "' in servlet context.";
log.error(msg);
throw new RuntimeException(msg);
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]