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.