Hi, You can pass the application name (application.getName()) to the manually started threads and later use it to lookup the Application when needed: Application.get(appName).
If you can understand Scala then you can use https://github.com/wicketstuff/core/blob/master/jdk-1.6-parent/scala-extensions-parent/wicket-scala/src/main/scala/org/wicketstuff/scala/FutureModel.scala#L53 as inspiration. On Thu, Apr 4, 2013 at 11:08 AM, Martin Dietze <[email protected]> wrote: > I recently migrated my legacy project from Wicket 1.4 to 6.6. > In this project there is a batch job for sending out > newsletters. As you might expect, in those newsletters there are > links to contents from the system. > > In the old system this was done like this (1.4 code): > > | public CharSequence > getApplicationRelativeUrlFor(IBookmarkablePageRequestTarget target) { > | if (!MyApplication.exists()) { > | final MyApplication application = (MyApplication) > MyApplication.get("MyApplication"); > | MyApplication.set(application); > | application.newRequestCycle(null, null); > | } > | for (final IRequestTargetUrlCodingStrategy strat : > getCodingStrategies()) { > | if (strat.matches(target)) { > | final CharSequence relativeURL = strat.encode(target); > | return relativeURL.toString(); > | } > | } > | return null; > | } > > The method 'getCodingStrategies()' returns all coding strategies that > were created at startup and subsequently added to a list which is returned > here. > > To me it seems like the above pretty much exploits some implementation > details of Wicket 1.4, however my predecessors did not seem to know another > way out. This project contains a bit of a content management system, in > which for different kinds of contents there are different mount points and > often even totally different IRequestTargetUrlCodinStrategy's, thus I > don't really see any alternative to asking Wicket which has this > information. > > Now, based on Wicket 6.6.0 the above does no longer work, obviously due > to the way the 'Application' object is initialised and then stored. > > My code looks pretty much like this: > > | public CharSequence getApplicationRelativeUrlFor( > BookmarkablePageRequestHandler handler) { > | MyApplication application = WicketUtil.checkMyApplication(); > | > | try { > | IRequestMapper mapper = application.getRootRequestMapper(); > | if ( mapper == null ) { > | throw new IllegalStateException( "Internal error, no root > request mapper configured!" ); > | } > | final Url url = mapper.mapHandler( handler ); > | return url; > | } finally { > | WicketUtil.cleanupDummyApplication( application ); > | } > | } > > If no application exists, I tried creating a dummy version of it, this > is done somewhere inside the 'checkMyApplication()' method, and it boils > down to this here: > > | public static MyApplication createDummyApplicationAndRequestCycle() { > | MyApplication application = new MyApplication( true ); > | final MockServletContext servletContext = new MockServletContext( > application, null ); > | application.setServletContext( servletContext ); > | WicketFilter wicketFilter = new WicketFilter( application ); > | try { > | wicketFilter.init( true, new FilterConfig() { > | @Override > | public ServletContext getServletContext() { > | return servletContext; > | } > | > | @Override > | public Enumeration<String> getInitParameterNames() { > | return Collections.enumeration( Collections.<String> > emptyList() ); > | } > | > | @Override > | public String getInitParameter( final String name ) { > | return null; > | } > | > | @Override > | public String getFilterName() { > | return "MyApplication"; > | } > | } ); > | } catch ( final ServletException e ) { > | throw new IllegalStateException( "Exception caught", e ); > | } > | if ( RequestCycle.get() == null ) { > | final ServletContext context = application.getServletContext(); > | > | final HttpSession newHttpSession = new MockHttpSession( context > ); > | final MockHttpServletRequest servletRequest = new > MockHttpServletRequest( application, newHttpSession, context ) { > | > | @Override > | public String getServletPath() { > | return getServletPathOtherCodeReliesOn(); > | } > | }; > | final MockHttpServletResponse servletResponse = new > MockHttpServletResponse( servletRequest ); > | > | servletRequest.initialize(); > | servletResponse.initialize(); > | > | final ServletWebRequest webRequest = new ServletWebRequest( > servletRequest, servletRequest.getFilterPrefix() ); > | > | final WebResponse webResponse = new BufferedWebResponse( new > ServletWebResponse( webRequest, servletResponse ) ); > | > | RequestCycle requestCycle = application.createRequestCycle( > webRequest, webResponse ); > | ThreadContext.setRequestCycle( requestCycle ); > | } > | > | return application; > | } > > Cleaning up the dummy application looks like this: > > | public static void cleanupDummyApplication( MyApplication application ) { > | if ( !application.isDummy() ) { > | return; > | } > | ThreadContext.setApplication( null ); > | } > > Of course this is very inefficient if I have to do this each time > a batch job queries for an URL. > > When I now run this in a batch job, I find that the dummy application is > created only once, though I attempt to remove it from the ThreadContext. > Also, after this has happened, when I open a page from the system in the > browser, I find that I've created an inconsistent state within the system, > getting this exception: > > | java.lang.IllegalStateException: Application with name 'MyApplication' > already exists.' > | at org.apache.wicket.Application.setName(Application.java:864) > | at > org.apache.wicket.protocol.http.WicketFilter.init(WicketFilter.java:373) > | at > org.apache.wicket.protocol.http.WicketFilter.init(WicketFilter.java:336) > | at > org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:259) > | at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237) > | at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) > | at > com.freiheit.commons.sensor.SensorFilter.doFilter(SensorFilter.java:812) > | at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) > | at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) > | at > ch.qos.logback.classic.helpers.MDCInsertingServletFilter.doFilter(MDCInsertingServletFilter.java:51) > | at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) > | at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) > | at > org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277) > | at > org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188) > | at > org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641) > | at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97) > | at > com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85) > | at > org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185) > | at > org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325) > | at > org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226) > | at > com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165) > | at > com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791) > | at > com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693) > | at > com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954) > | at > com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170) > | at > com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) > | at > com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) > | at > com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) > | at > com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) > | at > com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) > | at > com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) > | at com.sun.grizzly.ContextTask.run(ContextTask.java:69) > | at > com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330) > | at > com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309) > | at java.lang.Thread.run(Thread.java:619) > > OK, enough code shown here. I am asking myself if there is any totally > different, > and presumably much simpler way to do this? I mean, in principle querying > the web > framework for an URL from a batch job does not seem totally uncommon to > me, so maybe > there already is a mechanism to achieve something like this? > > Else, if not, is there any correct way to initialize an Application and > fake a request > from within my batch job, so that Wicket finds the environment it needs to > run the > request mappers on my bookmarkable handler? > > Any help *greatly* appreciated, I've already spent far too many hours on > this :/ > > Cheers, > > M'bert > > -- > ----------- / http://herbert.the-little-red-haired-girl.org / > ------------- > =+= > Die groessten Liebesgeschichten sind die, die nie stattgefunden haben > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [email protected] > For additional commands, e-mail: [email protected] > > -- Martin Grigorov jWeekend Training, Consulting, Development http://jWeekend.com <http://jweekend.com/>
