users@jersey.java.net

Re: ServletContainer jar scanning exception

From: Richard Wallace <rwallace_at_thewallacepack.net>
Date: Thu, 03 Jan 2008 17:29:32 -0800

Paul Sandoz wrote:
> Hi Richard,
>
> Richard Wallace wrote:
>> I was revisiting this issue recently to try and get it working with
>> 'mvn jetty:run'
>
> Glad you raised this issue again since recently i was wondering what
> we could do about it :-)
>
>
>> and decided to have a look at how the struts2 codebehind plugin
>> works. I pretty much needs to do the same thing, scan for classes
>> implementing an interface or with a certain annotation. To do this
>> they use the ResolverUtil class from XWork2
>> (http://svn.opensymphony.com/svn/xwork/trunk/src/java/com/opensymphony/xwork2/util/ResolverUtil.java).
>>
>>
>> The basic idea seems to be that you can use the
>> ClassLoader.getResources() method with a package name and it will
>> give you a list of resources in that package.
>>
>
> I did not know that ClassLoader.getResources could return a URL to a
> directory where class files reside!
>
> For example:
>
> Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().
> getResources("");
> while(urls.hasMoreElements()) {
> System.out.println(urls.nextElement());
> }
>
> Unfortunately there seems no consistent way to get the complete set of
> base URLs to stuff of the class loader :-( and therefore no
> zero-config approach.
>

Hmm you're right. It only seems to return the classes directory. That
is unexpected and disappointing. I wonder if looking for a common list
of top level packages, "com", "net", "org" for example, would be "good
enough".

>
>> So there should be no need to specify where the class files and jars
>> are.
>>
>
> But instead package names do need to be specified.
>

Yeah, I had thought that using a blank package name would give you
everything and I'm not even happy with my above suggestion of using some
common top level package names.

> Arguably this requires more configuration knowledge that is likely to
> change, for example if i add a new resource in a different package to
> my existing resources then i need to include that package (and if i
> refactor then i need to change it). Compile-time tools can help but
> they do complicate the build and deploy process (which is why we moved
> away from them). I think this gets more complicate when we consider
> message readers and writers (see end of email).

This isn't too much of an issue for me because my resources will almost
certainly live under a package like com.myco.myapp.rest and it is
extremely unlikely that will change. So I'm perfectly happy to set this
single parameter at the beginning of a project and forgetting about it.

>
> I very much like the idea of a zero-config build and deploy approach
> by default.

I've found that an absolutely zero-config is a good thing to strive for,
but not always - I'd maybe even say rarely - attainable.

>
> Hmmm... perhaps we could do the following:
>
> Have a PackageResourceConfig that takes a list of package names that
> are transformed into URLs (like what Struts does) that are then
> scanned for classes (using ASM). The PackageResourceConfig class and
> the package names for the PackageResourceConfig instance could be
> passed as servlet init-params. That should work consistently for the
> two forms of Jetty deployment.
>
> What do you think?

Sounds fine to me. Any idea when you plan on tackling this?

>
> BTW i am curious if you tried setting the servlet init-param:
>
> "com.sun.ws.rest.config.property.ResourcePaths"
>
> to the absolute location of where the class files reside in the dev
> deploy case? i.e. whether the Servlet.getRealPath works in such cases.

I didn't try it because I figured it would work but wasn't a long term
solution.

>
>
>
> For 0.6 the ResourceConfig stuff needs to be refactored to also return
> message readers and writer classes. Dynamically finding such things is
> IMHO better that using META-INF/services. Then we can also defer
> creation of readers/writers to an IoC framework.
>
> Paul.
>
>> Rich
>>
>> Paul Sandoz wrote:
>>> Richard Wallace wrote:
>>>> Alright, I did a bit more digging. I hadn't noticed that check for
>>>> if it is a directory. The problem is that since I'm running jetty
>>>> with the maven-jetty-plugin jetty:run target (super useful for
>>>> debugging), the /WEB-INF/lib and /WEB-INF/classes directories don't
>>>> exist.
>>>
>>> It is odd that context.getRealPath("/WEB-INF/lib") is actually
>>> returning something non-null though, so in some sense they must
>>> exist "Jim, but not as we know it".
>>>
>>>
>>>> With the jetty:run target, the plugin doesn't assemble the war, it
>>>> runs everything in place and tells jetty what it should use for the
>>>> classpath.
>>>>
>>>
>>> OK. See the JavaDoc of:
>>>
>>> com.sun.ws.rest.spi.container.servlet.ServletContainer
>>>
>>> perhaps you could set the init-param:
>>>
>>> com.sun.ws.rest.config.property.ResourcePaths
>>>
>>> to point to the relevant locations? I guess it all depends on what
>>> base path for context.getRealPath() with Jetty for a non-standard
>>> deployment config.
>>>
>>> Another workaround is to create your own class that extends
>>> DynamicResourceConfig with an empty public constructor that
>>> configures things from the java.class.path system property (see the
>>> com.sun.ws.rest.api.container.ContainerFactory code). Then set up
>>> the web.xml to point to this class using the "webresourceclass"
>>> init-param.
>>>
>>>
>>>> This is what is causing the scanning code to die. The solution is
>>>> to use the jetty:run-war target instead. The bad thing about
>>>> running the plugin that way is that changes to things like jsps and
>>>> templates don't just automatically get used, the webapp has to be
>>>> redeployed. A pain but something I can live with.
>>>>
>>>> As you said, more error handling code would have made this much
>>>> easier to track down.
>>>>
>>>
>>> Tis done.
>>>
>>> Paul.
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>