PDA

View Full Version : how to apply validation class to web servce



tdu
04-24-2006, 08:19 PM
I have a web service called CreateContact, I want to apply some logic do some validation before call CreateContact. How do I use springNet Aop to config my validation classes.

Web method class


public void CreateContact(Contact contact)
{
//do create contact logic
}

public bool EmailDupValidation(Contact contact)
{
//check email duplicate in contact.email field

}

public bool validationMethod2(Contact contact)
{
//another method to do validation
}


I want to the Aop configuration to do just like the following logic:
if (EmailDupValidation && validationMethod2)
CreateContact(contact)

How would I do that?

Thanks

.ben
04-25-2006, 07:51 AM
I don't know if you can apply advice on webservices...(edit: seems like you can :p) But for what's it worth I give you my 0.02.

Create an interface for the CreateContact, and one for the two validation methods. Implement the CreateContact in one class and the validation interface in another. Apply advice on the first, I would use AroundAdvice (http://www.springframework.net/doc/reference/html/aop-quickstart.html#aop-quickstart-basics-advice). In this advice you create an object or retrieve it from spring using IoC and perform your validation, if it works you continue otherwise you don't call the proceed method. I would seperate both things, that's just my gut feeling.

But if you really want the creation and the validation in the same class you can also call them in the aroundadvice.


public object Invoke(IMethodInvocation invocation)
{
CreateValidate obj = invocation.This as CreateValidate ;
if (obj.EmailDupValidation() && obj.validationMethod2())
invocation.Proceed();
else
//whatever you want
}

Where CreateValidate is like the code you attached.

#edit 2: http://www.springframework.net/doc/reference/html/web.html#web-webservices take a look at "12.10.6. Exporting an AOP Proxy as a Web Service".

tdu
04-25-2006, 08:22 PM
Thanks ben.
Ok, I can create Aop called CreateContact, then, I want to apply Before Advice differently based on some condition or business requirement.
E.g
I want to acheive this:
call validate1
call validate2
CreateContact
for one application. But for another application I want to do this:
call validate1
call validate3
CreateContact.

I want to dynmically config what applies before advice createContact. How would I achieve this.

Thanks.

Tony

.ben
04-26-2006, 07:36 AM
That's not really an aop issue, if I understand it correctly. Isolate the change and encapsulate it. Just plug in the correct validator in the advice.



public class Contact
{
private string m_name;

public Contact()
{
m_name = String.Empty;
}

public Contact(String name)
{
m_name = name;
}

public String Name
{
get
{
return m_name;
}
set
{
m_name = value;
}
}
}
public interface ICreateContactValidator
{
bool Validate(Contact contact);
}

public class ValidatorNoEmptyName : ICreateContactValidator
{

#region ICreateContactValidator Members

public bool Validate(Contact contact)
{
return ! contact.Name.Equals(String.Empty);
}

#endregion
}
public class CreateContactValidateAdvice : IMethodInterceptor
{
private ICreateContactValidator m_validator;
public CreateContactValidateAdvice(ICreateContactValidato r validator)
{
m_validator = validator;
}

public object Invoke(IMethodInvocation invocation)
{
Contact contactToValidate;
Object returnValue;
contactToValidate = invocation.Arguments[0] as Contact;
if (m_validator.Validate(contactToValidate))
returnValue = invocation.Proceed();
else
throw new ArgumentException("Validation failed");
return returnValue;
}
}

public interface IContactService
{
void CreateContact(Contact contact);
}
public class ContactService : IContactService
{
#region IContactService Members

void IContactService.CreateContact(Contact contact)
{
//Save to the database
}

#endregion
}

tdu
04-26-2006, 04:38 PM
Thanks ben. That's great.
Is there any way to dynamicaaly inject the validation rule to the ContactValidationAdvice.

public object Invoke(IMethodInvocation invocation)
{
Contact contactToValidate;
Object returnValue;
contactToValidate = invocation.Arguments[0] as Contact;
if (m_validator.Validate(contactToValidate))
returnValue = invocation.Proceed();
else
throw new ArgumentException("Validation failed");
return returnValue;
}


I want

Contact contactToValidate;
Object returnValue;
contactToValidate = invocation.Arguments[0] as Contact;
if (m_validator.Validate(contactToValidate))
....Proceed();


to be in a configurations so I can add/change rules more dynamically without compile the code. E.g. I want to add another exist rule to my contactToValidate, I want to acheve only add that rule to the configuration without changing the Invoke method. Is that possible?

Thanks for all you help!

Tony

.ben
04-26-2006, 08:55 PM
Well, first things first. In the example I supplied you would not need to change the advice to inject a different validator. You just need to implement the interface and change the configuration file.

To answer your question: well I see two solutions. Solution one: Create around advice for every rule you want to add and .layer (http://www.springframework.net/doc/reference/html/aop-quickstart.html#aop-quickstart-going-deeper-layering-advice) your advice. Drawbacks, you'll allways forget something or the customer will allways ask for yet another rule. So you still need to write yet another validator and advice.

Solution two: use the advice as supplied in my example but change the m_validator so that you can configure what methods needs to be called on supplied objects. I don't know if this can be done with spring, it can be done with reflection.

I don't really like either solution and would stick to the way I described earlier. In case of the exist rule:




public class ValidatorTwo : ICreateContactValidator
{

private m_contactDao;

public ValidatorTwo(IContactDAO contactDao)
{
m_contactDao = contactDao;
}
#region ICreateContactValidator Members

public bool Validate(Contact contact)
{
return ((! contact.Name.Equals(String.Empty)) && ! m_contactDao.Exists(contact));
}

#endregion
}

I did not check the code in this last class in VS, you could also combine severall validators in one so that last call.


public bool Validate(Contact contact)
{
return (m_NameValidator.Validate(contact) && ! m_contactDao.Exists(contact));
}

Up to you now ;).