[ 
https://issues.apache.org/jira/browse/OODT-613?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13766627#comment-13766627
 ] 

Ross Laidlaw commented on OODT-613:
-----------------------------------

Hi Rishi,

I've been experimenting with a design for configurable writers.  Here's an 
explanation of my work so far:

I was thinking it would be great if we could allow users to select from 
multiple configurations per mime/content type.  In the URLs, we could use a 
query parameter (e.g. 'configuration') to select the configuration to use for 
each request.  The default would be no configuration, i.e. standard output, if 
the parameter isn't present.  For example:

{noformat}
http://[host]/fmprod/jaxrs/dataset.rss?productTypeId=urn:oodt:GenericFile&configuration=example
http://[host]/fmprod/jaxrs/dataset.rss?productTypeId=urn:oodt:GenericFile&configuration=georss
http://[host]/fmprod/jaxrs/product.json?productId=123&configuration=geojson
{noformat}

We could set this up by using a naming scheme for our context.xml parameters 
that point to the configuration files:

{code:xml|title=context.xml|borderStyle=solid}
<Context>
  ...
  <Parameter name="configuration.rss.example" 
value="[FMPROD_HOME]/rss-example.xml"/>
  <Parameter name="configuration.rss.georss" value="[FMPROD_HOME]/georss.xml"/>
  <Parameter name="configuration.json.geojson" value="/tmp/geojson.xml"/>
  ...
</Context>
{code}

The naming scheme could be as follows: "configuration.<format>.<name>" where 
<format> is the content/mime type that the configuration applies to (matching 
the extension in the URL, e.g. xml, rss, json) and <name> is the name of that 
particular configuration (matching the 'configuration' parameter in the URL).

In our JAX-RS servlet, we can read in all of these parameters, initialize each 
configuration object and store the objects in a data structure (e.g. 
Map<String, Map<String, Configuration>>, where the key of the parent map is the 
content/mime type and the keys of the submaps are the configuration names):

{code:java|title=CasProductJaxrsServlet.java|borderStyle=solid}
public void init(ServletConfig servletConfig) throws ServletException
{
  super.init(servletConfig);
  ServletContext context = servletConfig.getServletContext();

  ...

  // Create a map to store all of the configuration instances.
  // The parent map is keyed by content type (e.g. rdf, rss, json).
  // The sub-maps are keyed by configuration name (e.g. 'example', 'georss').
  // A specific configuration can therefore be retrieved using the content type 
and configuration name.
  Map<String, Map<String, Configuration>> configurationMap =
    new HashMap<String, Map<String, Configuration>>();

  // Iterate over all of the context parameters in context.xml.
  Enumeration<String> enumeration = context.getInitParameterNames();
  while (enumeration.hasMoreElements())
  {
    String parameterName = enumeration.nextElement();

    // Look for parameter names matching "configuration.<format>.<name>"
    if(parameterName.startsWith("configuration"))
    {
      String[] values = parameterName.split("\\.");
      if (values.length == 3)
      {
        String format = values[1];
        String name = values[2];
        String fileName = context.getInitParameter(parameterName);

        // Create a configuration and import details from the file.
        Configuration config = ConfigurationFactory.createInstance(format);
        config.initialize(fileName);

        // Add the new configuration instance to the map.
        if (configurationMap.containsKey(format))
        {
          configurationMap.get(format).put(name, config);
        }
        else
        {
          Map<String, Configuration> map = new HashMap<String, Configuration>();
          map.put(name, config);
          configurationMap.put(format, map);
        }
      }
      else
      {
        LOGGER.log(Level.FINE, "Configuration context parameter could not be 
parsed.");
      }
    }
  }

  // Store the map as a context attribute so that it can be accessed by 
services and/or resources.
  context.setAttribute("configurations", configurationMap);

  ...
}
{code}

(This will require some configuration classes (e.g. RdfConfiguration, 
RssConfiguration) that implement an interface 'Configuration', plus the 
ConfigurationFactory class.  The configuration code from the original packages 
will be ported to these classes (I've nearly completed working on that).)

Then, in our provider/writer classes we can use context injection to access the 
URL for the request and the servlet context.  From the URL we can check if the 
configuration parameter was supplied.  If so, we can access the servlet context 
attribute for our configuration objects (i.e. the map) to get the correct 
configuration object.  For example:

{code:java|borderStyle=solid}
  ... 

  @Context
  private ServletContext context;

  @Context
  private UriInfo uriInfo;

  ...

  public void writeTo(Resource resource, Class<?> type,
    Type genericType, Annotation[] annotations, MediaType mediaType,
    MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
      throws IOException, WebApplicationException
  {
    // Check if we received a valid 'configuration' query parameter
    String configurationName = 
uriInfo.getQueryParameters().getFirst("configuration");
    if (configurationName != null && !configurationName.trim().equals(""))
    {
      // Get the map of configuration objects from the servlet context.
      Map<String, Map<String, Configuration>> formatsMap = 
        (Map<String, Map<String, Configuration>>)
          context.getAttribute("configurations");

      // Get the the sub-map for this writer/provider.
      Map<String, Configuration> namesMap = formatsMap.get("rss");

      // Get the configuration object from the map using the supplied parameter.
      Configuration configuration = namesMap.get(configurationName);

      if (configuration != null)
      {
        ...
      }
    }

    ...
  }

  ...
{code}

I have a basic example working quite well for RSS, so I'm hoping to supply a 
full patch before Monday's deadline.

Ross
                
> Make the content writers configurable for the JAX-RS service
> ------------------------------------------------------------
>
>                 Key: OODT-613
>                 URL: https://issues.apache.org/jira/browse/OODT-613
>             Project: OODT
>          Issue Type: Sub-task
>          Components: product server
>    Affects Versions: 0.6
>            Reporter: Ross Laidlaw
>            Assignee: Ross Laidlaw
>              Labels: gsoc2013
>             Fix For: 0.7
>
>
> Allow the content writers implemented in OODT-612, e.g. the RDF and RSS 
> writers, to be configured via configuration files (e.g. XML files).  This 
> feature is available for the RDF and RSS servlets in the original web 
> application.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to