You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@ant.apache.org by Antoine Levy-Lambert <an...@gmx.de> on 2011/02/01 16:04:55 UTC

Re: Ant + Spring = classpath purgatory

I think it is log4j which wants to look for config files on the thread 
context loader.

Regards,

Antoine

On 1/29/2011 1:27 PM, Mitch Gitman wrote:
> Here's the solution that finally worked for me, and that includes locating
> the log4j class. This is all in my Ant task:
>
>          ClassPathXmlApplicationContext applicationContext = new
> ClassPathXmlApplicationContext();
>          applicationContext.setClassLoader(this.getClass().getClassLoader());
>          applicationContext
>                  .setConfigLocation("com/foo/ApplicationContext.xml");
>          applicationContext.refresh();
>
> I'm going to clean this up to make the application layer initialize its own
> ApplicationContext internally. The caller/consumer of the application will
> just be responsible for passing a ClassLoader to the application layer. To
> my mind, having to supply a ClassLoader is the least evil--the smallest
> concession to the need for this application to be run by an Ant task as
> opposed to some other execution environment.
>
> Still, I'm curious why an executing task uses the ClassLoader obtained by
> LoaderUtils.getContextClassLoader() rather than the task's own
> AntClassLoader.
>
> On Sat, Jan 29, 2011 at 12:26 AM, Mitch Gitman<mg...@gmail.com>  wrote:
>
>> Here's another old post that corroborates the one I linked to:
>> http://www.mail-archive.com/user@ant.apache.org/msg22871.html
>>
>> This poster isolated the problem with the base class of
>> ClassPathXmlApplicationContext,
>> org.springframework.core.io.DefaultResourceLoader. And I notice that
>> DefaultResourceLoader does have a setClassLoader method:
>>
>> http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/core/io/DefaultResourceLoader.html#setClassLoader%28java.lang.ClassLoader%29
>>
>> This has the makings of a possibly more elegant solution. So I get:
>>
>>          AntClassLoader taskloader = (AntClassLoader)
>> this.getClass().getClassLoader();
>>
>> And then I pass this this AntClassLoader to
>> DefaultResourceLoader.setClassLoader. I'll give this a shot. Might solve my
>> log4j problem in the process.
>>
>> I'm still curious why this classloader isn't used in the first place and
>> what the default one, as obtained by LoaderUtils.getContextClassLoader(),
>> represents. This goes back to my observation that this sort of problem
>> doesn't arise elsewhere.
>>
>> Note. I'm using Ant 1.7.1.
>>
>>
>> On Fri, Jan 28, 2011 at 11:33 PM, Mitch Gitman<mg...@gmail.com>  wrote:
>>
>>> I have a Spring-based application that I'm exposing through an Ant task,
>>> among other interfaces.
>>>
>>> The moment where I run into trouble is when the application tries to use
>>> Spring's ClassLoader-based code to load a Spring application context:
>>>          ApplicationContext applicationContext = new
>>> ClassPathXmlApplicationContext(
>>>                  "/com/foo/ApplicationContext.xml");
>>>
>>> I see an error that the resource com/foo/ApplicationContext.xml cannot be
>>> found on the classpath. The XML file, together with the application code,
>>> happen to be in the same JAR as the task itself.
>>>
>>> Now, I came across this very, very old post on the ant-dev list that gave
>>> me the makings of a solution:
>>> http://www.mail-archive.com/dev@ant.apache.org/msg07704.html
>>>
>>> So at the start of my task, I would do this:
>>>          AntClassLoader taskloader = (AntClassLoader)
>>> this.getClass().getClassLoader();
>>>          taskloader.setThreadContextLoader();
>>>
>>> And at the close of my task, I would do this:
>>>          taskloader.resetThreadContextLoader();
>>>
>>> This works actually.*
>>>
>>> I'm leery though of having to resort to this fix. Does anyone know of a
>>> "better" way to get Spring to use the right ClassLoader or just in general
>>> to fool task-invoked application code that might play fast and loose with
>>> classloaders? I haven't delved into the Spring source myself. What's odd is
>>> that this problem doesn't arise in other classloading containers in which a
>>> Spring-based application might be running. For example, a web container
>>> would be loading a web application with a child classloader, and yet that
>>> works fine.
>>>
>>> Thanks.
>>>
>>> * Rather, this almost works. Almost in that Spring tries to configure its
>>> logging through log4j, but it can't find the class
>>> org.apache.log4j.Category. I've verified that the log4j JAR is in my
>>> classpath. The quick fix is to stick the log4j JAR in the Ant lib directory.
>>> Obviously, that is not a sustainable solution. I'm still trying to get to
>>> the bottom of this and might have to write a follow-up message.
>>>
>>


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@ant.apache.org
For additional commands, e-mail: user-help@ant.apache.org