Hi all,

I work with Pax Web on Karaf 4.3.0. I am trying to register Servlet with 
exact url, but I see url pattern is auto-generated from alias.
I look at the current master branch - version 8.0.0-SNAPSHOT. Class:

org.ops4j.pax.web.service.spi.model.ServletModel


constructor:
#ServletModel(org.ops4j.pax.web.service.spi.model.ContextModel, 
javax.servlet.Servlet, java.lang.String, java.lang.String[], 
java.lang.String, java.util.Dictionary<java.lang.String,?>, 
java.lang.Integer, java.lang.Boolean, javax.servlet.MultipartConfigElement)


it calles method ( private static )
new String[]{aliasAsUrlPattern(alias)}


    private static String aliasAsUrlPattern(final String alias) {
        String urlPattern = alias;
        if (urlPattern != null && !urlPattern.equals("/")
                && !urlPattern.contains("*")) {
            if (urlPattern.endsWith("/")) {
                urlPattern = urlPattern + "*";
            } else {
                urlPattern = urlPattern + "/*";
            }
        }
        return urlPattern;
    }


so it always creates a url pattern, as I guess the name suggest, but why? I 
would like to register exact URL, not the pattern. As it looks now, this is 
not possible to do - as there is no argument to pass in to control the flow.

As it looks from the git history/log this is quite "old" code - from 2008 - 
2013, so I guess this is not new and I guess everybody are ok with this? So 
in this case, what is the usecase for it? As for my usecase - this is not 
the required behavior.

For example, Servlet, registered with /hello, also matches /hello/1, but I 
want /hello/1 to return HTTP 404.


So for now, only really question is - is this expected behavior or is there 
a room to change this? If so, how can one, with existing solution, register 
Servlet with exact URL?

Exact strack of calls looks like this:

<init>:53, ServletModel (org.ops4j.pax.web.service.spi.model)
registerServlet:224, HttpServiceStarted (org.ops4j.pax.web.service.internal)
registerServlet:210, HttpServiceStarted (org.ops4j.pax.web.service.internal)
registerServlet:69, HttpServiceProxy (org.ops4j.pax.web.service.internal)
register:97, ServletWebElement 
(org.ops4j.pax.web.extender.whiteboard.internal.element)
registerWebElement:392, WebApplication 
(org.ops4j.pax.web.extender.whiteboard.internal)
addWebElement:188, WebApplication 
(org.ops4j.pax.web.extender.whiteboard.internal)
addingService:193, AbstractTracker 
(org.ops4j.pax.web.extender.whiteboard.internal.tracker)
addingService:46, AbstractTracker 
(org.ops4j.pax.web.extender.whiteboard.internal.tracker)
customizerAdding:941, ServiceTracker$Tracked (org.osgi.util.tracker)
customizerAdding:870, ServiceTracker$Tracked (org.osgi.util.tracker)
trackAdding:256, AbstractTracked (org.osgi.util.tracker)
track:229, AbstractTracked (org.osgi.util.tracker)
serviceChanged:901, ServiceTracker$Tracked (org.osgi.util.tracker)
invokeServiceListenerCallback:990, EventDispatcher 
(org.apache.felix.framework)
fireEventImmediately:838, EventDispatcher (org.apache.felix.framework)
fireServiceEvent:545, EventDispatcher (org.apache.felix.framework)
fireServiceEvent:4595, Felix (org.apache.felix.framework)
registerService:3587, Felix (org.apache.felix.framework)
registerService:348, BundleContextImpl (org.apache.felix.framework)
registerService:355, BundleContextImpl (org.apache.felix.framework)

I've changed this in my branch, added additional method with same name and 
initParams:

private static String aliasAsUrlPattern(final String alias, final 
Dictionary<String, ?> initParams) {
   final Object exactUrlPatternFromAliasParam = 
initParams.get("exactUrlPattern");
   Boolean exactUrlPatternFromAlias = Boolean.FALSE;
   if (null != exactUrlPatternFromAliasParam) {
      if (exactUrlPatternFromAliasParam instanceof String) {
         final String flag = ((String) 
exactUrlPatternFromAliasParam).toLowerCase();
         exactUrlPatternFromAlias = Boolean.parseBoolean(flag);
       } else if(exactUrlPatternFromAliasParam instanceof Boolean) {
         final Boolean flag = (Boolean) exactUrlPatternFromAliasParam;
         exactUrlPatternFromAlias = flag;
      } else if (exactUrlPatternFromAliasParam instanceof Serializable) {
         final String flag = 
exactUrlPatternFromAliasParam.toString().toLowerCase();
         exactUrlPatternFromAlias = Boolean.parseBoolean(flag);
       }
   }
   final String result;
   if (Boolean.TRUE.equals(exactUrlPatternFromAlias)) {
      // Break the reference
      result = alias.toString();
   } else {
      result = aliasAsUrlPattern(alias);
   }
   return result;
}


This calls original unmodified version of method aliasAsUrlPattern.

Caller has to pass additional init parameter "exactUrlPattern". I usually 
call it with Boolean.TRUE. I guess flag could/should be added into 
org.ops4j.pax.web.extender.whiteboard.ExtenderConstants.

To note one other thing -- this is " one of the use cases ", I as see there 
is also construction, that allows to pass in defined url patterns, but I 
did not find how to call it. The call I am using is:

props.put(ExtenderConstants.DEFAULT_INIT_PREFIX_PROP + "exactUrlPattern", 
Boolean.TRUE);
bundleContext.registerService(Servlet.class, new 
WhiteboardServlet("/hello"), props);

Could be, that if HttpService interface is used, this is not the case.

I've tried to solve this using

props.put(ExtenderConstants.PROPERTY_URL_PATTERNS, "/hello");

This is illegal state as implemented by the constructor of class:

org.ops4j.pax.web.extender.whiteboard.internal.element.ServletWebElement

if (alias != null && urlPatterns != null && urlPatterns.length != 0) {
    LOG.warn("Registered servlet [{}] cannot have both alias and url 
patterns.", getServiceID());
    valid = false;
}


I did not look into this yet, but why is this implemented like so? If this 
would be changed, it would make use of existing constants.


Kind Regards,
Miroslav


-- 
-- 
------------------
OPS4J - http://www.ops4j.org - ops4j@googlegroups.com

--- 
You received this message because you are subscribed to the Google Groups 
"OPS4J" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to ops4j+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/ops4j/179c33ab-fdd3-451f-b4ff-57f2fc934a04%40googlegroups.com.

Reply via email to