all groups > dotnet xml > august 2004 >
You're in the

dotnet xml

group:

System.Xml.XmlValidatingReader.set_ValidationType raised InvalidOperationException



System.Xml.XmlValidatingReader.set_ValidationType raised InvalidOperationException jesse.elve NO[at]SPAM t4g.com
8/31/2004 11:09:21 AM
dotnet xml: I am using an XmlValidatingReader which uses an XSD for xml
validation. The code has been performing reliably for months.
Yesterday it failed for the first time with the following exception:

Inner exception of type System.InvalidOperationException has occurred
: The operation is not valid due to the current state of the object.
[source = System.Xml]
[method call = set_ValidationType]
[stack trace = at
System.Xml.XmlValidatingReader.set_ValidationType(ValidationType
value)

As I said, this code has been quite some time. It has been tested and
is now in a production system in a critical code path. When it failed
it caused a significant financial transaction to fail. I am wondering
if anyone has ever seen this behaviour or has any recommendations.

The offending code is as follows:

private static XmlValidatingReader vReader = null;
private static XmlSchemaCollection xsc = new XmlSchemaCollection();
// . . .
StringReader sr = new StringReader(xsdString);
XmlTextReader schemaReader = new XmlTextReader(sr);
xsc.Add(null, schemaReader);
// . . .
vReader = new XmlValidatingReader(candidate);
vReader.Schemas.Add(xsc);
Re: System.Xml.XmlValidatingReader.set_ValidationType raised InvalidOperationException Zafar Abbas [MSFT]
8/31/2004 2:45:42 PM
This exception would be caused when the ReadState of the validaitng reader
is not set to ReadState.Initial, which imples that the validating reader was
moved ahead( via a call to Read() ) before setting the ValidationType
property.

Could you share your original code and data files?

Thanks.
Zafar


[quoted text, click to view]

Re: System.Xml.XmlValidatingReader.set_ValidationType raised InvalidOperationException Dare Obasanjo [MSFT]
8/31/2004 4:39:31 PM
Definitely looks like a thread contention issue since your original code has
vReader as a static variable and you have no locks around the code. Locking
the code for the entire validation period is expensive and basically loses
all the benefits of using multiple threads. The simple answer is for vReader
not to be a static member variable.

--
This posting is provided "AS IS" with no warranties, and confers no rights.

[quoted text, click to view]

Re: System.Xml.XmlValidatingReader.set_ValidationType raised InvalidOperationException Jesse Elve
8/31/2004 6:48:11 PM
Zafar:

This has turned out to be a very interesting bug. I will be very pleased if
anyone will agree with me that the only possible cause is due to multiple
threads accessing the function simultaneously. (My supervisor thinks that
I'm jumping to this conclusion too hastily!)

In any event, the exception was raised on the final line of the following
code excerpt (!):

vReader = new XmlValidatingReader(candidate);
vReader.Schemas.Add(xsc);
vReader.ValidationType = ValidationType.Schema;

Note that this is an _exact_ excerpt. As you can see, there is _no_
possibility that "read" is called before the "ValidationType" is set, as the
reader has just been instantiated 2 lines up!

This becomes more interesting when the full class is considered:

-------------------------------------------------------------------------
public class OrderValidator
{
private static XmlValidatingReader vReader = null;
private static XmlSchemaCollection xsc = new XmlSchemaCollection();

private OrderValidator()
{
// Access XSD as an embedded resource in this assembly:
System.Reflection.Assembly myAssembly;
myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
System.Resources.ResourceManager myManager = new
System.Resources.ResourceManager("xxx.xxx.xxx.xxx.Order_XSD",
myAssembly);
string xsdString =
myManager.GetString("Order_xsd",System.Globalization.CultureInfo.InvariantCu
lture); // this is case-sensitive
StringReader sr = new StringReader(xsdString);
XmlTextReader schemaReader = new XmlTextReader(sr);

// Add XSD to schemaCollection
xsc.Add(null, schemaReader);
}

/// <summary>
/// Singleton instance via .NET-Framework-managed singleton semantics
/// </summary>
public static readonly OrderValidator Instance = new OrderValidator();

/// <summary>
/// Validation method
/// </summary>
/// <param name="candidate">fresh XMLTextReader (unread!)</param>
/// <returns>true for valid XML or throws an exception for
failure</returns>
public Boolean Validates(XmlTextReader candidate)
{
Boolean isValid = false;
vReader = new XmlValidatingReader(candidate);
vReader.Schemas.Add(xsc);
vReader.ValidationType = ValidationType.Schema;
try
{
while (vReader.Read()){}
isValid = true;
}
catch(Exception e)
{
string message = "Validation failed: ";
message += "Element name: " + (vReader.Name != null ? vReader.Name :
String.Empty) + ". ";
message += "Element value: " + (vReader.Value != null ? vReader.Value :
String.Empty) + ". ";
throw(new ApplicationException(message, e));
}
return isValid;
}

}
-------------------------------------------------------------------------

There were numerous factors which made it logical to design this class as a
Singleton, chiefly the size and complexity of the XSD. Once instantiated,
the singleton instance of this class does service validation requests from
multiple threads.

The only explanation that I can come up with is that 2 contending threads
are in the "Validates" method simultaneously. I'm very open to any other
explanation!

In the meantime, I have already implemented the following modifications
based on my "thread contention" theory:

--------------------------------------------------------------------------

// object used for method-level locking
private static Object privateStaticObject = new Object();

public Boolean Validates(XmlTextReader candidate)
{
Boolean isValid = false;
lock (privateStaticObject)
{
vReader = new XmlValidatingReader(candidate);
vReader.Schemas.Add(xsc);
vReader.ValidationType = ValidationType.Schema;
try
{
while (vReader.Read()){}
isValid = true;
}
catch(Exception e)
{
string message = "Validation failed: ";
message += "Element name: " + (vReader.Name != null ? vReader.Name :
String.Empty) + ". ";
message += "Element value: " + (vReader.Value != null ? vReader.Value :
String.Empty) + ". ";
throw(new ApplicationException(message, e));
}
}
return isValid;
}

--------------------------------------------------------------------------

Based on a previous incident, however, our architect thinks I'm too quick to
jump to a "thread contention" conclusion. If anyone has any other
interpretations or suggestions please let me know!

Re: System.Xml.XmlValidatingReader.set_ValidationType raised InvalidOperationException Jesse Elve
9/1/2004 11:55:06 AM
Thanks,

In retrospect, that seems obvious!


[quoted text, click to view]

AddThis Social Bookmark Button