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.