8

The web designer has given me HTML which looks like:

<div .... style="background: transparent url(xxx.png) 170px center no-repeat">

Unfortunately the contents of the image xxx.png is generated by the software, so I have made it a WebResource and use the following strategy to generate the URL for the resource which I then embed in the style= attribute using a Wicket AttributeModifier.

// App initialization code
String resourceName = ....;
getSharedResources().add(resourceName, myWebResource);

// Creating the widget
String url = getServletContext().getContextPath()
    + "/resources/org.apache.wicket.Application/" + resourceName ;
String style = "background: transparent url(" + url + ") 170px center no-repeat";
div.add(new AttributeModifier("style", new Model<String>(style)));

This works fine when I test it locally using Eclipse, but :

  • When I install this in production, I want to have Apache as a proxy to Jetty such that the context root isn't visible, i.e. Apache forwards a request of /foo onto Jetty as /context-root/foo.
  • In general, I don't think this is very elegant. I'm sure I am duplicating Wicket code here?

I understand Wicket solves this problem of context-roots and Apache proxying by only using relative URLs. That would be the most elegant solution I suspect. But if I have e.g. a IndexedParamUrlCodingStrategy then the URL could be of arbitrary length and I don't know how many .. to include to get back to /resources.

Edit: The current solution is to use absolute URLs as in my code example above, and in Apache (a) rewrite /context-root/* into /* (b) as before then ADD the context root to all requests (c) forward to Jetty. That way most URLs can be without the context root but some URLs (to my resources) can have the context root and it's OK. But I don't like this solution!

Adrian Smith
  • 17,236
  • 11
  • 71
  • 93
  • 1
    This doesn't answer the question, but you could simplify the last line a bit: `new SimpleAttributeModifier("style", style)` – Jonik Nov 01 '10 at 20:08

2 Answers2

14

If the code is called from inside a component (or page):

urlFor(new ResourceReference("sharedResourceName"));

or

RequestCycle.get().urlFor(new ResourceReference("sharedResourceName"));

Sample application below. I used a ByteArrayResource for simplicity, but any Resource subclass will do:

WicketApplication.java

package app1;

import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.request.target.coding.IndexedParamUrlCodingStrategy;
import org.apache.wicket.resource.ByteArrayResource;

public class WicketApplication extends WebApplication {
    @Override
    protected void init() {
        super.init();
        getSharedResources().add("testResource", new ByteArrayResource("text/plain", "This is a test".getBytes()));
        mount(new IndexedParamUrlCodingStrategy("home/very/deep/folder", getHomePage()));
    }
    public Class<HomePage> getHomePage() {
        return HomePage.class;
    }
}

HomePage.java

package app1;

import org.apache.wicket.PageParameters;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.behavior.SimpleAttributeModifier;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.WebPage;

public class HomePage extends WebPage {
    public HomePage(final PageParameters parameters) {
        CharSequence resourceHref = urlFor(new ResourceReference("testResource"));
        add(new Label("link", "Click me!")
            .add(new SimpleAttributeModifier("href", resourceHref)));
    }
}

HomePage.html

<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
    <body>
        <a wicket:id="link"></a>
    </body>
</html>
tetsuo
  • 10,726
  • 3
  • 32
  • 35
  • 1
    Perfect! Wicket is so well thought out. So I knew it had to be possible. Thanks very much! :) – Adrian Smith Nov 19 '10 at 08:02
  • Thanks but. what if there was no RequestCycle associated with current thread? – Hossein Nasr Sep 09 '14 at 14:52
  • 1
    I'm using Wicket 6 and this doesn't seem to work anymore. The ResourceReference(string) constructor is not there, anche the ResourceReference class is now Abstract and needs to be implemented. Is there any other easy way to get a shared resource's URL? – Master_T Jul 06 '16 at 07:45
0

I think the tactic used in this answer for creating dynamic image urls will apply here.

Community
  • 1
  • 1
Don Roby
  • 40,677
  • 6
  • 91
  • 113
  • As far as I can see that creates and registers the resource with Wicket; this bit I can do. However I don't know how I can get access to the URL to that resource, apart from manually generating the URL like in my example. I'm worried if Wicket one day changes the way the URLs to resources works, my code will break. Wicket must have the code somewhere to work out URLs to resources, so it should be possible for me to use it rather than re-coding it...? – Adrian Smith Nov 02 '10 at 15:23