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/>

Reply via email to