As our WS implementation is dictionary-based, we need –
at some point – to read our terms dictionary, i.e., a file containing a list of
terms. As this is an expensive operation we only want to do this once for the
whole WS so that any later web method calls can reuse the terms
dictionary and therewith be faster. In our tutorial implementation we will do
this file reading in an extra initialization method which is only called if the
initialization has not been done before, i.e., only once. This method will then
read the terms dictionary and use it to create a new instance of an OpenNLP
DictionaryNameFinder
(package opennlp.tools.namefind); the latter will be used to find terms, then.
Here is the new initialize
method and a new field for
the created term finder:
/** the finder to use for identifying terms in sentences */ private TokenNameFinder termFinder = null; /** * Initializes this WS implementation, if necessary. * * @throws InternalServiceFault * in case there is any internal problem from which the WS * cannot recover */ private synchronized void initialize() throws InternalServiceFault { if (this.termFinder != null) return; this.termFinder = new DictionaryNameFinder(readTermDictionary()); }
readTermDictionary
method which returns a
Dictionary
(package opennlp.tools.dictionary); we still need to develop this method,
though.
Reading a file in Java is pretty straightforward – as long as you know where to find that file, i.e., as long as you have the complete path to the file. Unfortunately, reading a file from a WS poses just this problem: we may know the relative path to the file from the context root of the WS but usually we don’t know where this context root lies in the file system of the application server that has deployed our WS. The solution to this problem is to let the application server give us this location at deployment time. This is done using resource injection with the following lines of code:
@Resource private WebServiceContext wsContext = null;
wsContext
variable with the correct context for our WS. This context can
then be used in our readTermDictionary
method as
follows:
/** path to the terms dictionary file */ private static final String TERMS_DICT_FILE_PATH = "/res/terms.list"; /** * Reads the terms dictionary which is specified by * {@link #TERMS_DICT_FILE_PATH} and returns it. The file has to contain one * term per line where the tokens of each term are separated by whitespaces. * * @return the read terms dictionary * @throws InternalServiceFault * in case there is some IO problem from which the WS cannot * recover */ private Dictionary readTermDictionary() throws InternalServiceFault { try { return Dictionary .parseOneEntryPerLine(new InputStreamReader(WebServiceTools .getServletContext(this.wsContext) .getResourceAsStream(TERMS_DICT_FILE_PATH), "UTF-8")); } catch (UnsupportedEncodingException e) { // should never happen throw new InternalServiceFault( "Could not read the term dictionary.", e.getMessage(), e); } catch (IOException e) { throw new InternalServiceFault( "Could not read the term dictionary.", e.getMessage(), e); } }
getServletContext
method
from the QALL-ME Framework’s WebServiceTools
(package net.sf.qallme) for
convenience to get from the WS context to the servlet context.
Therewith the initialization of our simple WS implementation is done.