1. Application context xmls looks as below
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:test="http://www.test.xyz/schema"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.test.xyz/schema http://www.test.xyz/schema-1.0.xsd">
<test:person name="suji"/>
</beans>
Now the xsd mentioned in the schema location should map to something.
2. You shoudl have a spring.schemas file in the META-INF directory
http\://www.test.xyz/schema-1.0.xsd=com/test/test-1.0.xsd
This maps the schema to teh lcoation of teh xsd
3. Xsd looks like
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.test.xyz/schema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:element name="person">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Configures all required interactions with the named Control Bus configuration
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="name" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Identifies group-name of a Control Bus this configuration defines
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:schema>
We have a single element person with attribute as name which is a string.
4. Now each element in the xsd should map to a resolver.
This can be mentioned in spring.handlers file which is also in the META-INF directory
http\://www.test.xyz/schema=com.test.PersonNamespaceHandler
5. Implementaion of PersonNamespaceHandler
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class PersonNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("person", new PersonParser());
}
}
6. Parser implementation
public class PersonParser extends AbstractBeanDefinitionParser {
private String beanName;
/* This method gets the parameters mentioned in the custom namespace and helps building
custom logic based on it */
@Override
protected AbstractBeanDefinition parseInternal(Element element,
ParserContext parserContext) {
BeanDefinitionBuilder rootBuilder = BeanDefinitionBuilder
.rootBeanDefinition(Person.class.getName());
beanName = element.getAttribute("name");
//Ensuring name is a compulsary attribute
Assert.hasText(beanName, "'name' must be provided");
rootBuilder.addPropertyValue("name", beanName);
return rootBuilder.getBeanDefinition();
}
protected String resolveId(Element element,
AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
return beanName;
}
}
7. Custom classes for Person
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Test case for trying out this
public class PersonParserTest {
public static void main(String[] arg){
ApplicationContext ac = new ClassPathXmlApplicationContext("config.xml", PersonParserTest.class);
Person person = (Person) ac.getBean("suji");
System.out.println("Person: " + person.getName());
}
}
Wednesday, November 18, 2009
Writing Custom Namespaces in Spring
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment