Creating a New SAML Object
Creating a new SAML Object requires creating an interface and four classes: a concrete implementation, a builder, a marshaller, and an unmarshaller. The OpenSAML code serve as good examples of these items. Once you have written these items you should refer to the Configuration File section of the manual to see how to configure them for usage.
Create an Interface
The first thing you should do is create an interface for your object. This will allow people to extend/replace your implementation in the future without breaking existing code. Here are the rules we use internally when creating our interfaces:
- Name the Java interface the same as the XML element/type it's representing; if the element is
Attribute, then the interface name is Attribute.
- Create a final static String called DEFAULT_ELEMENT_LOCAL_NAME whose value is the local part of the XML element's name
- Create a final static QName called DEFUALT_ELEMENT_NAME whose value is the fully qualified name of element
- Create a final static String called TYPE_LOCAL_NAME whose value is the local part of the schema type's name (if there is a custom schema type)
- Create a final static QName called TYPE_NAME whose value is the fully qualified name of the schema type (if there is a custom schema type)
- Create a final static String called *_ATTRIB_NAME for each element attribute; * is replaced by the attribute name and the value is the attribute name
- Create getters and setters for each attribute and single-instance occurring child element
- Create getters that return a List for each multiple-instance occurring child element.
Create a Concrete Implementation of your Interface
Next you need to create a concrete implementation of your interface. Here are some suggestions for doing that:
- Consider extending
org.opensaml.common.impl.AbstractSignableSAMLObject(for elements that can be digitally signed). These classes provide a significant amount of boiler plate code.
- Make your constructor protected so that user's cant invoke it but your builder can
- Each SAMLObject maintains a cache of its DOM representation, be sure to use the
prepareForAssignment()methods when assigning values to fields so that this cached DOM is improperly invalidated when changes occur
org.opensaml.xml.util.XMLObjectChildrenListas the backing List implementation when you need to store a single type of multi-value children
org.opensaml.xml.util.IndexedXMLObjectChildrenListas the backing List implementation when you need to store multiple types of multi-value children. Use the subList() method expose views of the List that only contain SAMLObjects of with a certain element QName or schema type. As an example you may wish to look at org.opensaml.saml2.metadata.impl.EntityDescriptorImpl and how it handles RoleDescriptor children.
- Initialize each List in your constructor
- If your extending an existing SAMLObject implementation be sure that when you override getOrderedChildren() that you also include the children from the superclass in your returned list.
Create an Element Builder
Create a class that:
- Extends org.opensaml.common.impl.AbstractSAMLObjectBuilder, providing the your interface as the parameterized type
- Has a no-argument constructor
- Is stateless
- Returns an object implementing the element's interface, described above.
Additional Configuration Information
If your class requires additional configuration information this can be provided in the OpenSAML configuration file; refer to the Extending the !ObjectProvider section for more information.
Next you will need to create a marshaller and unmarshaller for your new object. See the following sections in this manual to do that: