Hello

Yes - this is all confusing... I'm just in the process of reviewing master
branch (pax web 8.0.0-SNAPSHOT) to check R7 (and even R6) compliance....
There's really lot to do still...

Indeed - I checked
org.ops4j.pax.web.service.spi.model.ServletModel#aliasAsUrlPattern() and it
really changes alias like "/something" into "/something/*", but Http
Service specification explicitly says (102.2 Registering Servlets):

For example, if the Http Service implementation is listening to port 80 on
the machine www.acme.com and the Servlet object is registered with the
*name* "/servlet" [...]

I noticed that the spec is not clear about "name" vs. "alias" vs. "URI
pattern"... And I believe your interpretation is the correct one - "alias"
is "exact URI pattern"... Of course it still doesn't tell anything about
actual context to use for servlet registration (I'm just working on making
it less confusing in pax web 8).

So the only recommendation I have for you is not to use direct registration
(httpService.registerServlet()), but to use whiteboard approach and
register Servlet.class OSGi service using
"BundleContext.registerService(Servlet.class, servlet, props)" where
properties include either:

props.put("urlPatterns", new String[] { "/hello" }); // old Pax Web approach

or:

props.put("osgi.http.whiteboard.servlet.pattern", new String[] { "/hello"
}); // new R6+ Whiteboard approach (chapter 140.4 "Registering Servlets").

I hope this helps and explains the confusion.

regards
Grzegorz Grzybek

czw., 6 lut 2020 o 12:14 Miroslav Beranič <[email protected]>
napisał(a):

> 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 - [email protected]
>
> ---
> 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 [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/ops4j/179c33ab-fdd3-451f-b4ff-57f2fc934a04%40googlegroups.com
> <https://groups.google.com/d/msgid/ops4j/179c33ab-fdd3-451f-b4ff-57f2fc934a04%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
-- 
------------------
OPS4J - http://www.ops4j.org - [email protected]

--- 
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/ops4j/CAAdXmhrwbGPxu-CGNiy-oFLtV981uU93L_UfOYSPcrpWY2Mu2w%40mail.gmail.com.

Reply via email to