You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@commons.apache.org by "Frank W. Zammetti" <fz...@omnytex.com> on 2005/04/25 22:29:23 UTC

[Digester] Unable to get validation working

Hey all... I'm trying to use validation with Digester for the first time
and not having any luck.

In my code, I have this:

digester.setValidating(true);
digester.register("myconfig",
this.getClass().getResource("my-config.dtd").toString());

That second line throws an NPE.  The my-config.dtd is in WEB-INF.  In my
XML file to be parsed and validated I have:

<!DOCTYPE myconfig SYSTEM "WEB-INF/my-config.dtd">

I should point out that when I remove those two lines my config file is
parsed properly, so I know it's choking on the DTD...

I can only assume the DTD is not being found (no error messages other than
an NPE displayed, logging is set to log everything to the console).  I've
tried various paths in the getResource call including
"WEB-INF/my-config.dtd", "/WEB-INF/my-config.dtd" and of course just the
filename as above.  I pretty much assume I'm just not using Digester right
as far as validation goes, so can someone point me in the right direction?
 Thanks in advance.

-- 
Frank W. Zammetti
Founder and Chief Software Architect
Omnytex Technologies
http://www.omnytex.com

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


Re: [Digester] Unable to get validation working

Posted by Joey Overby <jo...@realgo.com>.
Hi,
  I just joined this list and am confused about the status of this project. 
I can't seem to find any sort of release, and had to hack it together.  Is 
there somewhere I can download a 'decently' stable build of it?

Thank you,
 Joey Overby
----- Original Message ----- 
From: "Wendy Smoak" <ja...@wendysmoak.com>
To: "Jakarta Commons Users List" <co...@jakarta.apache.org>
Sent: Monday, April 25, 2005 5:21 PM
Subject: Re: [Digester] Unable to get validation working


> From: "Frank W. Zammetti" <fz...@omnytex.com>
>
>>digester.register("myconfig",
>>this.getClass().getResource("my-config.dtd").toString());
>
>> Makes sense Wendy... I gave it a shot, but still get the NPE on that
>> line (must be the toString() call that's actually throwing it).
>
> Does it work if you hard-code whatever is supposed to be there?  (What 
> value
> are you expecting?)
>
> Simon should be along any minute to give you the answer... :)
>
> -- 
> Wendy Smoak
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-user-help@jakarta.apache.org
>
>
> 



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


Re: [Digester] Unable to get validation working

Posted by "Frank W. Zammetti" <fz...@omnytex.com>.
On Tue, April 26, 2005 1:13 am, Craig McClanahan said:
> This exact same code will also work if you had your DTD at
> "/WEB-INF/lib/classes/my/app/myConfig.dtd" -- because the
> WEB-INF/classes directory is also placed on the classpath for you.

That's what Wendy said too.  Makes sense (now) :)

> PUBLIC is definitely what you want for this sort of thing.  There's
> also conventional formats for the public identifier and system
> identifier if this DTD was going to be a public thing ... but it
> doesn't matter for application private things.

I need to go do a little reading on DOCTYPE because it doesn't seem to
have *quite* the meaning I thought it had.  Just different enough for
something like this to bite me basically :)

> Now that you got this working (sorry I didn't get a chance to respond
> earlier) ...

No problem.  Wendy was helpful in nudging me in the right direction.

> there actually is a way to access resources that are in
> WEB-INF but not in the classpath.  That's because ServletContext has
> getResource() and getResourceAsStream() methods just like Class does.
>
>     ServletContext context = ...;
>     URL cURL = context.getResource("/WEB-INF/myConfig.dtd");
>     digester.register("myConfig", cURL.toString());

Ironically, I do this in another application where I'm parsing an app
config file manually (written before I discovered Digester), and it looks
virtualy identical to what you have here :)  Although, I'm not sure in my
head I knew there was a difference between getResource called on Class vs.
called on ServletContext, but it seems obvious now there would be :)  Good
info in case.

Frank


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


Re: [Digester] Unable to get validation working

Posted by "Frank W. Zammetti" <fz...@omnytex.com>.
On Tue, April 26, 2005 2:22 am, Simon Kitching said:
> Yep. All XML document declarations really should have a PUBLIC
> identifier. Ones that have only a system identifier are extremely
> "fragile" in that they expect the machine they are processed on to have
> the dtd available in a specific place.
>
> The whole purpose of the PUBLIC identifier is to be able to redirect
> requests for the associated dtd to some arbitrary file, in exactly the
> way you want to do via the "Digester.register(publicId, URL)" method.

This is the part that confused me in the end the most... so then it would
be correct to say that the location specified in the DOCTYPE declaration
is overridden by what you specify with the call to register(), correct? 
If so, that's the point I didn't realize (and frankly just guessed at in
the end to solve this)... that's why specifying public didn't seem right
to me in the first place, I figured the location had to be valid, which
wouldn't be the case here.

> And as Craig says, the public ID really should be a much longer and much
> more unique string than just "myConfig", so that software that deals
> with many different xml document types can tell them apart. However if
> this particular document is only expected to be fed into pieces of
> software that deal with just this document type then you can get away
> with this.

I see... in this case this document would only be read by a Struts plugin,
so yeah, I should be able to get away with it.  I think I'll just go make
it longer none the less, no harm no foul :)

> By the way, if you get confused you can always avoid Digester's
> validation support and set things up the traditional way, ie you can
> always do
>   digester.setValidating(true);
>   SAXParser parser = digester.getParser();
> then call the SAXParser methods directly to configure validation (in
> particular, setting a custom EntityResolver via
> parser.setEntityResolver). This won't bother the digester at all;
> digester really doesn't care much about validation as that occurs within
> the parser before events are passed to Digester.

The problem is, I've never before had a need to validate a document before
parsing, I've always just gone directly to parsing (kind of odd that that
would be true now that I say it, but it is!).  So, my experience wasn't
quite up to this in this case :)

>
> One other thing you should watch out for when enabling validation: by
> default, Digester will ignore errors reported by the parser (other than
> logging them). You will need to register a custom error handler in order
> to take appropriate action when an error occurs (which probably just
> means throwing the parameter object as an exception):
>    digester.setErrorHandler(myCustomErrorHandler)
> or
>    digester.getParser().setErrorHandler(myCustomErrorHandler)
> The only difference between these two is that the first allows Digester
> to log a message before forwarding to your custom errorhandler.

Cool.  I did notice that execution happily continued when a parse error
occurred (until something that needed the results of the parsed document
tried to execute of course).  I appreciate that heads-up, as well as the
rest of your explanation here Simon, it was all very helpful (as was Wendy
and Craig's responses) :)

Frank

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


Re: [Digester] Unable to get validation working

Posted by Simon Kitching <sk...@apache.org>.
On Mon, 2005-04-25 at 22:13 -0700, Craig McClanahan wrote:
> > 
> > The last piece of the puzzle though, which took about 45 minutes of
> > banging my head on the desk to figure out, was the DOCTYPE definition in
> > the XML file I was trying to validate.  I had to use:
> > 
> > <!DOCTYPE myConfig PUBLIC "myConfig" "myConfig">
> > 
> > It seemed more logical to use SYSTEM, but it kept trying to pull the
> > file from various locations on the local file system, as the name
> > indicates).  Even when I tried to get the path to point at the actual
> > file in WEB-INF for instance though, it would never work for one reason
> > or another.  This, even though it doesn't seem right to me (and maybe
> > it's not!) *does* work.
> > 
> 
> PUBLIC is definitely what you want for this sort of thing.  There's
> also conventional formats for the public identifier and system
> identifier if this DTD was going to be a public thing ... but it
> doesn't matter for application private things.

Yep. All XML document declarations really should have a PUBLIC
identifier. Ones that have only a system identifier are extremely
"fragile" in that they expect the machine they are processed on to have
the dtd available in a specific place.

The whole purpose of the PUBLIC identifier is to be able to redirect
requests for the associated dtd to some arbitrary file, in exactly the
way you want to do via the "Digester.register(publicId, URL)" method.

SYSTEM identifiers are not meant to be redirectable - they literally
reference a local file. This is why there is no
"Digester.register(systemId, URL)" method. If there is no public ID, or
the public ID is not "registered", then Digester just tries to use the
SYSTEM id as a literal reference to a file - which, in your case, it
couldn't find. Of course if you really are stuck with a bad xml file
that only has a SYSTEM id (this happens) you can write your own
EntityResolver rather than relying on Digester to do this work.

And as Craig says, the public ID really should be a much longer and much
more unique string than just "myConfig", so that software that deals
with many different xml document types can tell them apart. However if
this particular document is only expected to be fed into pieces of
software that deal with just this document type then you can get away
with this.

> 
> > Cool, one step closer to completion!
> > 

Good luck.

By the way, if you get confused you can always avoid Digester's
validation support and set things up the traditional way, ie you can
always do
  digester.setValidating(true);
  SAXParser parser = digester.getParser();
then call the SAXParser methods directly to configure validation (in
particular, setting a custom EntityResolver via
parser.setEntityResolver). This won't bother the digester at all;
digester really doesn't care much about validation as that occurs within
the parser before events are passed to Digester.


One other thing you should watch out for when enabling validation: by
default, Digester will ignore errors reported by the parser (other than
logging them). You will need to register a custom error handler in order
to take appropriate action when an error occurs (which probably just
means throwing the parameter object as an exception):
   digester.setErrorHandler(myCustomErrorHandler)
or
   digester.getParser().setErrorHandler(myCustomErrorHandler)
The only difference between these two is that the first allows Digester
to log a message before forwarding to your custom errorhandler.


Regards,

Simon


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


Re: [Digester] Unable to get validation working

Posted by Craig McClanahan <cr...@gmail.com>.
On 4/25/05, Frank W. Zammetti <fz...@omnytex.com> wrote:
> Whew!  Got it!
> 
> Wendy, you WERE right, at least partially, in terms of the point on
> pathing... what I wound up doing was putting the DTD in a JAR in the
> webapp lib directory, so it's of course in the path.  In the code I do:
> 
> URL cURL = this.getClass().getResource("my/app/myConfig.dtd");
> digester.register("myConfig", cURL.toString());
> 
> ...where the path in the getResource() call matches the path where the
> DTD is in the JAR.

This exact same code will also work if you had your DTD at
"/WEB-INF/lib/classes/my/app/myConfig.dtd" -- because the
WEB-INF/classes directory is also placed on the classpath for you.

> 
> The last piece of the puzzle though, which took about 45 minutes of
> banging my head on the desk to figure out, was the DOCTYPE definition in
> the XML file I was trying to validate.  I had to use:
> 
> <!DOCTYPE myConfig PUBLIC "myConfig" "myConfig">
> 
> It seemed more logical to use SYSTEM, but it kept trying to pull the
> file from various locations on the local file system, as the name
> indicates).  Even when I tried to get the path to point at the actual
> file in WEB-INF for instance though, it would never work for one reason
> or another.  This, even though it doesn't seem right to me (and maybe
> it's not!) *does* work.
> 

PUBLIC is definitely what you want for this sort of thing.  There's
also conventional formats for the public identifier and system
identifier if this DTD was going to be a public thing ... but it
doesn't matter for application private things.

> Cool, one step closer to completion!
> 

Now that you got this working (sorry I didn't get a chance to respond
earlier) ... there actually is a way to access resources that are in
WEB-INF but not in the classpath.  That's because ServletContext has
getResource() and getResourceAsStream() methods just like Class does.

    ServletContext context = ...;
    URL cURL = context.getResource("/WEB-INF/myConfig.dtd");
    digester.register("myConfig", cURL.toString());

> Frank

Craig

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


Re: [Digester] Unable to get validation working

Posted by "Frank W. Zammetti" <fz...@omnytex.com>.
Whew!  Got it!

Wendy, you WERE right, at least partially, in terms of the point on 
pathing... what I wound up doing was putting the DTD in a JAR in the 
webapp lib directory, so it's of course in the path.  In the code I do:

URL cURL = this.getClass().getResource("my/app/myConfig.dtd");
digester.register("myConfig", cURL.toString());

...where the path in the getResource() call matches the path where the 
DTD is in the JAR.

The last piece of the puzzle though, which took about 45 minutes of 
banging my head on the desk to figure out, was the DOCTYPE definition in 
the XML file I was trying to validate.  I had to use:

<!DOCTYPE myConfig PUBLIC "myConfig" "myConfig">

It seemed more logical to use SYSTEM, but it kept trying to pull the 
file from various locations on the local file system, as the name 
indicates).  Even when I tried to get the path to point at the actual 
file in WEB-INF for instance though, it would never work for one reason 
or another.  This, even though it doesn't seem right to me (and maybe 
it's not!) *does* work.

Cool, one step closer to completion!

Frank

Frank W. Zammetti wrote:
> That's a good question (what am I expecting to be there)... I don't know 
> actually... I'm either not understanding the documentation, or the 
> documentation isn't as clear as it could be because I'm not really sure 
> what should be there.  I know it accepts a string of course, but beyond 
> that I'm not sure.
> 
> Wendy Smoak wrote:
> 
>> From: "Frank W. Zammetti" <fz...@omnytex.com>
>>
>>> digester.register("myconfig",
>>> this.getClass().getResource("my-config.dtd").toString());
>>
>>
>>
>>> Makes sense Wendy... I gave it a shot, but still get the NPE on that
>>> line (must be the toString() call that's actually throwing it).
>>
>>
>>
>> Does it work if you hard-code whatever is supposed to be there?  (What 
>> value
>> are you expecting?)
>>
>> Simon should be along any minute to give you the answer... :)
>>
> 

-- 
Frank W. Zammetti
Founder and Chief Software Architect
Omnytex Technologies
http://www.omnytex.com


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


Re: [Digester] Unable to get validation working

Posted by "Frank W. Zammetti" <fz...@omnytex.com>.
That's a good question (what am I expecting to be there)... I don't know 
actually... I'm either not understanding the documentation, or the 
documentation isn't as clear as it could be because I'm not really sure 
what should be there.  I know it accepts a string of course, but beyond 
that I'm not sure.

Wendy Smoak wrote:
> From: "Frank W. Zammetti" <fz...@omnytex.com>
> 
>>digester.register("myconfig",
>>this.getClass().getResource("my-config.dtd").toString());
> 
> 
>>Makes sense Wendy... I gave it a shot, but still get the NPE on that
>>line (must be the toString() call that's actually throwing it).
> 
> 
> Does it work if you hard-code whatever is supposed to be there?  (What value
> are you expecting?)
> 
> Simon should be along any minute to give you the answer... :)
> 

-- 
Frank W. Zammetti
Founder and Chief Software Architect
Omnytex Technologies
http://www.omnytex.com


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


Re: [Digester] Unable to get validation working

Posted by Wendy Smoak <ja...@wendysmoak.com>.
From: "Frank W. Zammetti" <fz...@omnytex.com>

>digester.register("myconfig",
>this.getClass().getResource("my-config.dtd").toString());

> Makes sense Wendy... I gave it a shot, but still get the NPE on that
> line (must be the toString() call that's actually throwing it).

Does it work if you hard-code whatever is supposed to be there?  (What value
are you expecting?)

Simon should be along any minute to give you the answer... :)

-- 
Wendy Smoak



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


Re: [Digester] Unable to get validation working

Posted by "Frank W. Zammetti" <fz...@omnytex.com>.
Makes sense Wendy... I gave it a shot, but still get the NPE on that 
line (must be the toString() call that's actually throwing it).

Wendy Smoak wrote:
> From: "Frank W. Zammetti" <fz...@omnytex.com>
> 
>>In my code, I have this:
>>
>>digester.setValidating(true);
>>digester.register("myconfig",
>>this.getClass().getResource("my-config.dtd").toString());
>>
>>That second line throws an NPE.  The my-config.dtd is in WEB-INF.  In my
> 
> 
> For getResource(...) to work, wouldn't the file have to be on the classpath,
> so in WEB-INF/classes, not directly in WEB-INF?
> 
> I load .properties files from WEB-INF/classes with:
>          ClassLoader cl = UniSessionFactory.class.getClassLoader();
>          InputStream input = cl.getResourceAsStream( propsFileName );
> and this seems similar.  The javadocs say that the getResource method
> "delegates the call to its class loader" after making some changes.
> 
> HTH,
> Wendy Smoak
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-user-help@jakarta.apache.org
> 
> 
> 
> 
> 

-- 
Frank W. Zammetti
Founder and Chief Software Architect
Omnytex Technologies
http://www.omnytex.com


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


Re: [Digester] Unable to get validation working

Posted by Wendy Smoak <ja...@wendysmoak.com>.
From: "Frank W. Zammetti" <fz...@omnytex.com>

> In my code, I have this:
>
> digester.setValidating(true);
> digester.register("myconfig",
> this.getClass().getResource("my-config.dtd").toString());
>
> That second line throws an NPE.  The my-config.dtd is in WEB-INF.  In my

For getResource(...) to work, wouldn't the file have to be on the classpath,
so in WEB-INF/classes, not directly in WEB-INF?

I load .properties files from WEB-INF/classes with:
         ClassLoader cl = UniSessionFactory.class.getClassLoader();
         InputStream input = cl.getResourceAsStream( propsFileName );
and this seems similar.  The javadocs say that the getResource method
"delegates the call to its class loader" after making some changes.

HTH,
Wendy Smoak


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