2014-09-16 15:16 GMT+02:00 Konstantin Kolinko <knst.koli...@gmail.com>: > 2014-09-15 23:01 GMT+04:00 Romain Manni-Bucau <rmannibu...@gmail.com>: >> Hi guys, >> >> in TomEE I'd like to add a filter but after context filter are started >> (means filterStart() from StandardContext is called). >> > > Why? What is the use case? >
we add a filter with a tomee service (passing after tomee started) > You code adds filter definitions. A filter definitions just associates > filter with a name. A filter is unreachable if it has no mappings for > it. > Where are filter mappings for your filter? How do you add filter mappings? > full code is: final FilterDef filterDef = new FilterDef(); filterDef.setAsyncSupported("true"); filterDef.setDescription(description); filterDef.setFilterName(description); filterDef.setDisplayName(description); filterDef.setFilter(new CXFJAXRSFilter(cxfRsHttpListener, context.findWelcomeFiles())); filterDef.setFilterClass(CXFJAXRSFilter.class.getName()); context.addFilterDef(filterDef); String mapping = completePath; if (!completePath.endsWith("/*")) { if (completePath.endsWith("*")) { mapping = completePath.substring(0, completePath.length() - 1); } mapping = mapping + "/*"; } final String urlPattern = removeWebContext(webContext, mapping); cxfRsHttpListener.setUrlPattern(urlPattern.substring(0, urlPattern.length() - 1)); final FilterMap filterMap = new FilterMap(); filterMap.addURLPattern(urlPattern); filterMap.setFilterName(filterDef.getFilterName()); context.addFilterMap(filterMap); addFilterConfig(context, filterDef); // the hack I sent previously > When do you add your new filter? Is context already started and > serving requests, or it has not started yet? Why cannot you add > filter definition before a filterStart() call? > > Do you use "StandardContext" class directly, or you can subclass it? > directly, tomee doesn't change StandardContext (one big goal) > The proper solutions should be to add new API, but I would like the > answers on the above questions first, as > a) There shall be some API for filter mappings as well. > b) If context has already been started, implementation would be more > complicated. > >> What I do today is: >> > > Where do I start with this? > > Just several notes on the code. > > 1. Missing synchronization. filterStart() uses "synchronized > (filterConfigs)" Your code does not use synchronization. > Actually we don't care that much here since that's still in the start context (app is not yet fully usable) so multithreading shouldnt occur, does it in tomcat? > 2. If you using "setAccessible(true)", > > A simpler way would be to mark ApplicationFilterConfig constructor as > accessible and call it directly instead of playing with filterStart(). > > Playing with filterStart() without accompanying filterStop() call is broken > > filterStart() does "filterConfigs.clear();" as one of the first steps. > A lot of code in your method are a workaround against that clear() > call. (You copy the filterConfigs into a temporary map to preserve the > map entries from being cleared). Essentially this clear() call throws > away filter instances (wrapped in ApplicationFilterConfig classes) > without properly destroying them. > > You code might break if "filterConfigs" field were marked as"final" > (as it should be). > we already got this before in webapp classloader and until tomcat supports our feature we forced by reflection the field to not be final. That said I agree (and why I ask for a simpler API) that it is mainly workarounds but I don't see why StandardContext is not exposing it (what would be blocking). > > >> try { >> final Field def = >> StandardContext.class.getDeclaredField("filterDefs"); >> if (!def.isAccessible()) { >> def.setAccessible(true); >> } >> final Field config = >> StandardContext.class.getDeclaredField("filterConfigs"); >> if (!config.isAccessible()) { >> config.setAccessible(true); >> } >> final Object oldDefs = def.get(context); >> final Map<String, ApplicationFilterConfig> oldConfig = new >> HashMap<>((Map<String, ApplicationFilterConfig>) config.get(context)); >> try { >> final Map<String, FilterDef> tempDef = new HashMap<>(); >> tempDef.put(filterDef.getFilterName(), filterDef); >> def.set(context, tempDef); >> >> StandardContext.class.cast(context).filterStart(); > > Why such code style? The following is shorter. > ((StandardContext)context).filterStart(); > > >> // update configs >> oldConfig.putAll((Map<String, >> ApplicationFilterConfig>) config.get(context)); >> } finally { >> def.set(context, oldDefs); >> def.set(context, oldConfig); >> } >> } catch (final Exception e) { >> throw new IllegalStateException(e); >> } >> >> but it is really hacky just to get a ApplicationFilterConfig. Is there >> an easier way I miss or is it possible to make it a bit more easy? >> >> >> Romain Manni-Bucau >> Twitter: @rmannibucau >> Blog: http://rmannibucau.wordpress.com/ >> LinkedIn: http://fr.linkedin.com/in/rmannibucau >> Github: https://github.com/rmannibucau >> > > --------------------------------------------------------------------- > To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org > For additional commands, e-mail: dev-h...@tomcat.apache.org > --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org