It is possible for an extension to include servlets without having
to register those servlets in Tomcat's WEB-INF/web.xml
file. The extension needs to be in a JAR file as usual. The servlet class
should be located in the JAR file following regular Java conventions.
Eg. The class my.domain.ServletClass
should
be located at my/domain/ServletClass.class
. You
also need to create a second XML file that contains the servlet
definitions at META-INF/servlets.xml
. The format for
defining servlets in this file is very similar to how servlets are
defined in the web.xml
file. Here is an example:
<?xml version="1.0" encoding="UTF-8" ?> <servlets xmlns="http://base.thep.lu.se/servlets.xsd"> <servlet> <servlet-name>HelloWorld</servlet-name> <servlet-class>net.sf.basedb.examples.extensions.HelloWorldServlet</servlet-class> <init-param> <param-name>template</param-name> <param-value>Hello {user}! Welcome to the Servlet world!</param-value> </init-param> </servlet> </servlets>
The <servlets>
tag is the root tag and is
needed to set up the namespace and schema validation. This may contain
any number of <servlet>
tags, each one
defining a single servlet.
The <servlet-name>
tag contains the name
of the servlet. This is a required tag and must be unique among the servlets
defined by this extension. Other extensions may use the same name without any
problems.
The <servlet-class>
tag contains the name
of implementing class. This is required and the class must implement
the Servlet
interface and have a public,
no-argument constructor. We recommend that servlet implementations instead
extends the HttpServlet
class. This will make the
servlet programming easier.
A servlet may have any number <init-param>
tags, containing initialisation parameters for the servlet. Here is the
code for the servlet references in the above example.
public class HelloWorldServlet extends HttpServlet { private String template; public HelloWorldServlet() {} @Override public void init() throws ServletException { ServletConfig cfg = getServletConfig(); template = cfg.getInitParameter("template"); if (template == null) template = "Hello {user}."; } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { final SessionControl sc = Base.getExistingSessionControl(request, true); final DbControl dc = sc.newDbControl(); try { User current = User.getById(dc, sc.getLoggedInUserId()); PrintWriter out = response.getWriter(); out.print(template.replace("{user}", current.getName())); } finally { if (dc != null) dc.close(); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
Invoking the servlet is done with a URL that is constructed like:
$HOME$/[servlet-name].servlet
, where $HOME$
is the home directory of the extension. An alternate URL
that doesn't require the .servlet
extension is available:
$SERVLET_HOME$/[servlet-name]
, where $SERVLET_HOME$
is the home directory of servlets for the extension. Note that this
directory is on a different sub-path than the $HOME$
directory.
Extra path information is supported
if it is inserted between the servlet name and the .servlet
extension: $HOME$/[servlet-name][/extra/path/info].servlet
,
$SERVLET_HOME$/[servlet-name][/extra/path/info]
Query parameters are supported as normal:
$HOME$/[servlet-name].servlet?param1=value¶m2=value
,
$SERVLET_HOME$/[servlet-name]?param1=value¶m2=value
<extension id="net.sf.basedb.clients.web.menu.extensions.helloservletworld" extends="net.sf.basedb.clients.web.menu.extensions" > <index>5</index> <about> <name>Hello Servlet world</name> <description> This example uses a custom Servlet page to display the "Hello world" message instead of a javascript popup. </description> </about> <action-factory> <factory-class> net.sf.basedb.clients.web.extensions.menu.FixedMenuItemFactory </factory-class> <parameters> <title>Hello Servlet world!</title> <tooltip>Opens a Servlet generated page with the message</tooltip> <data-url>$HOME$/HelloWorld.servlet?ID=$SESSION-ID$</data-url> <data-popup>HelloServletWorld, 400, 300</data-popup> <icon>~/images/servlet.png</icon> </parameters> </action-factory> </extension>
Note | |
---|---|
To keep things as simple as possible, a new instance of the servlet class is created for each request. If the servlet needs complex or expensive initialisation, that should be externalised to other classes that the servlet can use. |