As has been discussed before, spring-faces doesn't seem to support relative views when the flow is defined in the classpath. In SWF-732 (which I don't seem to be able to link to, sorry), Keith mentions a workaround using a custom FlowResourceViewResolver. I haven't been able to locate any information on how to do this. I was wondering if anyone might have an example, or just some insight on where I might find more information on this? Thanks.
Announcement
Announcement Module
Collapse
No announcement yet.
Facelets views on the classpath
Page Title Module
Move
Remove
Collapse
X
-
I've done it at my work.
You have to extend com.sun.facelets.impl.ResourceResolver, and add a configuration to your web.xml. Here is a very simple implementation ...
Code:public class ClassPathResourceResolver implements ResourceResolver { public URL resolveUrl(String path) { return getClass().getResource(path); } }
HTML Code:<context-param> <param-name>facelets.RESOURCE_RESOLVER</param-name> <param-value>foo.bar.ClassPathResourceResolver</param-value> </context-param>
Code:protected FaceletFactory createFaceletFactory(Compiler c) { return new DefaultFaceletFactory(c, new ClassPathResourceResolver(), 2); }
-
Handled
For anyone who might wonder, I was able to solve this issue for my situation with some custom resource classes...nothing extensive though...
Extend UrlResource and implement ContextResource - this will allow Webflow to create the relative faces view id. It assumes "within context" means within a jar file...this may not work for views that are not within a jar file - I haven't tested it.
Code:package foo.bar; import org.apache.commons.lang.UnhandledException; import org.springframework.core.io.ContextResource; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.util.ResourceUtils; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; public class ContextUrlResource extends UrlResource implements ContextResource { public ContextUrlResource(URL url) { super(url); } public ContextUrlResource(URI uri) throws MalformedURLException { super(uri); } public ContextUrlResource(String path) throws MalformedURLException { super(path); } public String getPathWithinContext() { try { if (ResourceUtils.isJarURL(this.getURL())) { String path = this.getURL().getPath(); int start = path.lastIndexOf("!"); if (start > 0) { return path.substring(start + 2); // strip the leading "!/" from the path } } return this.getURL().getPath(); } catch (IOException e) { throw new UnhandledException("This should never happen.", e); } } @Override public Resource createRelative(String relativePath) throws MalformedURLException { try { return new ContextUrlResource(super.createRelative(relativePath).getURL()); } catch (IOException e) { throw new UnhandledException("We should never get an IOException here.", e); } } }
Code:package foo.bar; import org.springframework.web.context.support.ServletContextResourcePatternResolver; import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.Resource; import javax.servlet.ServletContext; import java.net.URL; public class CustomServletContextResourcePatternResolver extends ServletContextResourcePatternResolver { public CustomServletContextResourcePatternResolver(ServletContext servletContext) { super(servletContext); } public CustomServletContextResourcePatternResolver(ResourceLoader resourceLoader) { super(resourceLoader); } @Override protected Resource convertClassLoaderURL(URL url) { return new ContextUrlResource(url); } }
Code:package foo.bar; import org.springframework.web.context.support.XmlWebApplicationContext; import org.springframework.core.io.support.ResourcePatternResolver; public class CustomXmlWebApplicationContext extends XmlWebApplicationContext { @Override protected ResourcePatternResolver getResourcePatternResolver() { return new CustomServletContextResourcePatternResolver(this); } }
Code:<context-param> <param-name>contextClass</param-name> <param-value>foo.bar.CustomXmlWebApplicationContext</param-value> </context-param>
Comment
-
I would like to have flow+views in the same package, in classpath, and use relative view name in view-state, like this :
/foo/bar/my-flow.xml
/foo/bar/my-view.xhtml
Code:<view-state id="foo" view="my-view" />
I use a BeanPostProcessor to override all flowApplicationContext ResourceLoader in the FlowRegistry.
Code:public class FlowRegistryClassPathPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(bean instanceof FlowDefinitionRegistry) { alterRegistry((FlowDefinitionRegistry) bean); } return bean; } protected void alterRegistry(FlowDefinitionRegistry registry) { for(String flowId : registry.getFlowDefinitionIds()) { ApplicationContext ctx = registry.getFlowDefinition(flowId).getApplicationContext(); overrideResourceLoader((GenericApplicationContext) ctx); } } protected void overrideResourceLoader(GenericApplicationContext ctx) { ctx.setResourceLoader(new CustomFlowResourceLoader((ClassPathResource)ctx.getResource(""))); } }
Code:class CustomFlowResourceLoader implements ResourceLoader { private ClassPathResource base; public CustomFlowResourceLoader(ClassPathResource base) { this.base = base; } public ClassLoader getClassLoader() { return base.getClassLoader(); } public Resource getResource(String location) { return new CustomClassPathContextResource(base.getPath()+location, base.getClassLoader()); } }
Code:class CustomClassPathContextResource extends ClassPathResource implements ContextResource { public CustomClassPathContextResource(String path, ClassLoader classLoader) { super(path, classLoader); } public String getPathWithinContext() { return getPath(); } public Resource createRelative(String relativePath) { String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath); return new CustomClassPathContextResource(pathToUse, getClassLoader()); } }
Code:<bean class="foo.bar.FlowRegistryClassPathPostProcessor" />
Comment
-
My 2.0.7 solution
The solutions above didn't work a 100% for me, I needed to change a couple of things for SWF 2.0.7.
I've written about it on my blog here:
http://www.redcode.nl/blog/2009/12/s...ets-into-jars/
If anybody finds bugs/improvements, let me know, drop a comment on the site.
Comment
Comment