If you know Object-Oriented THEN you need to Spring

المشرف: Ahmedn1

If you know Object-Oriented THEN you need to Spring

مشاركةبواسطة amrSalah » الاثنين أكتوبر 26, 2009 3:33 pm

[align=left]What is Spring?
Frequently used acronyms

* API: Application programming interface
* IDE: Integrated Development Environment
* XML: Extensible Markup Language

Spring, a robust Java application framework developed by Rod Johnson, has gained wide acceptance within the Java development community. It is famous for high-tech buzz phrases such as "dependency injection," "inversion of control," and "aspect-oriented programming." It also supports the Model-View-Controller (MVC) pattern and plays nicely with various and sundry database drivers for data access. Additionally, it supports transaction management, unit testing, batch processing, and security.

Given its reputation and longevity, it is often seen as the "go-to" framework when rapid application development is required. And, perhaps best of all, it's free.

What is the O/X Mapper?

A new feature, as of Spring 3.0, is the O/X Mapper. The concept of an O/X mapper is not new. The O stands for Object. The X stands for XML. The idea is to translate a Java object (almost always a plain old Java object or POJO) into an XML document and vice versa.

So, for example, you might have a simple bean with a few attributes and you have a business need to translate that Java object into an XML document. Spring's O/X Mapper can handle that for you. If the reverse is true (that is, you need to take an XML document and translate it into a simple Java bean), Spring's O/X Mapper can also handle that.

Note at this point that the Spring O/X Mapper simply defines consistent interfaces that are implemented by popular third-party frameworks. To take advantage of Spring's O/X functionality, you need a utility that handles the translation from Java object to XML and vice versa. One popular third-party tool for that purpose is Castor, which I use in this article. Other tools are XMLBeans, Java Architecture for XML Binding (JAXB), JiBX, and XStream.

Marshalling versus unmarshalling

You frequently see the words marshalling and unmarshalling used in conjunction with O/X mapping.

Marshalling refers to the process of translating a Java bean into an XML document. This means that all of the bean's fields and field values are populated in the created XML file as XML elements or attributes. Sometimes marshalling is also called serializing.

Unmarshalling, as you might guess, is the exact opposite. It refers to the process of translating an XML document into a Java bean. This means that all of that document's elements or attributes are populated as Java fields in the Java bean, and the values of the elements or attributes become the values of those fields. Sometimes unmarshalling is also called deserializing.

Benefits of using Spring's O/X Mapper

One immediate benefit of using Spring's O/X Mapper is that you can simplify configuration by taking advantage of other aspects of the Spring framework. Spring's bean factory enables you to inject (that's the "dependency injection" thing that was mentioned earlier) instantiated O/X marshallers directly into the objects that use them. To repeat a previous point, this facilitates rapid application development and deployment.

Following solid object-oriented design practices, the Spring O/X framework simply defines two interfaces (Marshaller and Unmarshaller) which are used to execute the O/X functionality. This is another outstanding benefit of using the framework. The implementation of these interfaces is totally up to the individual developer, and they can be switched with ease so that coding changes are not required. For example, if you use Castor for O/X purposes but find that it lacks certain functionality that you require, you can instead switch to XMLBeans with no coding changes. You simply change the Spring configuration file to use the new O/X framework.

Another benefit of using Spring's O/X Mapper is the consistent exception hierarchy. The Spring framework follows the pattern established with its data access module by wrapping the original exception objects in Spring's own runtime exception established specifically for the O/X Mapper. Because the original exception thrown by the third-party provider is wrapped in the Spring runtime exception, you never lose the root cause of the exception. You also do not need to worry about altering code to catch a specific exception because it is wrapped in a runtime exception. The base exception, XMLMappingException, is extended by several other runtime exceptions, including GenericMarshallingFailureException, ValidationFailureException, MarshallingFailureException, and UnmarshallingFailureException.

A simple demonstration

Now that you understand the background and basics of Spring's O/X Mapper, it's time to take a look at how it is used. In this article, you first create a simple Spring application, independent of any Java Enterprise dependencies. You create a simple Java class that accesses Spring's configuration file to instantiate the class and inject the O/X dependency. Then you use an instance of this class to marshal and unmarshal a simple Java bean. For a link to all the source files, including configuration files, see Download.

Coding it

The first thing to notice is the Spring configuration file. Listing 1 is the configuration file that the application uses to perform the marshalling and unmarshalling. Please note that this file must be in the classpath at runtime.

Listing 1. The configuration file

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/b ... ns-3.0.xsd">

CODE: تحديد الكل

    
<bean id="oxmExample" class="com.xyz.OXMExample">
        <property name="marshaller" ref="castorMarshaller" />
        <property name="unmarshaller" ref="castorMarshaller" />
    </bean>
    <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller">
        <property name="mappingLocation" value="classpath:mapping.xml" />
    </bean>
</
beans>

  [code=php]  <bean id="oxmExample" class="com.xyz.OXMExample">
        <property name="marshaller" ref="castorMarshaller" />
        <property name="unmarshaller" ref="castorMarshaller" />
    </bean>  <bean id="oxmExample" class="com.xyz.OXMExample">
        <property name="marshaller" ref="castorMarshaller" />
        <property name="unmarshaller" ref="castorMarshaller" />
    </bean>[/code]
    <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller">
        <property name="mappingLocation" value="classpath:mapping.xml" />
    </bean>
</
beans>
 


As you can see, only two beans are defined. This keeps things simple. The first bean is the class (com.xyz.OXMExample) that is used to execute the demonstration. Two properties associated with that class use dependency injection. In both cases, they are injected with an instance of the castorMarshaller bean. This is the standard way to define beans within the Spring framework, as experienced Spring developers will immediately notice.

The other bean is the castorMarshaller bean itself. It is an instance of org.springframework.oxm.castor.CastorMarshaller, which essentially wraps the Castor framework. As mentioned previously, a third-party O/X framework is required to use Spring's O/X functionality. In this case, Castor is the third-party product of choice. Also, note that a property is defined with castorMarshaller. That is the mapping file used by Castor to map the Java bean to the XML output and vice versa. This file is called mapping.xml and must be in the classpath at runtime. I will explain the contents of the mapping.xml file shortly.

Listing 2 is an abbreviated listing of the code that will actually execute O/X mapper. As you can see, it is a fairly simple Java class.

Listing 2. The OXMExample class (abbreviated)
CODE: تحديد الكل

public class OXMExample 
{
    private static final String FILE_NAME = "simplebean.xml";
    private SimpleBean simpleBean;

    private Marshaller marshaller;
    private Unmarshaller unmarshaller;

    public void setMarshaller(Marshaller marshaller) {
        this.marshaller = marshaller;
    }

    public void setUnmarshaller(Unmarshaller unmarshaller) {
        this.unmarshaller = unmarshaller;
    }

    public void saveSimpleBean() throws IOException {
        FileOutputStream os = null;
        try {
            os = new FileOutputStream(FILE_NAME);
            this.marshaller.marshal(simpleBean, new StreamResult(os));
        } finally {
            if (os != null) {
                os.close();
            }
        }
    }

    public void loadSimpleBean() throws IOException {
        FileInputStream is = null;
        try {
            is = new FileInputStream(FILE_NAME);
            this.simpleBean 
                        
= (SimpleBean) this.unmarshaller.unmarshal(new StreamSource(is));
        } finally {
            if (is != null) {
                is.close();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        ApplicationContext appContext 
                        
= new ClassPathXmlApplicationContext("applicationContext.xml");
        OXMExample ex = (OXMExample) appContext.getBean("oxmExample");
        ex.go();
    }

    private void go() throws IOException {
        simpleBean = getSimpleBean();

        saveSimpleBean();
        loadSimpleBean();
        
        System
.out.println("name: " + simpleBean.getName());
        System.out.println("job description: " + simpleBean.getJobDescription());
        System.out.println("age: " + simpleBean.getAge());
        System.out.println("executive: " + simpleBean.isExecutive());
    }


    private SimpleBean getSimpleBean() {
        SimpleBean simpleBean = new SimpleBean();
        simpleBean.setAge(35);
        simpleBean.setExecutive(false);
        simpleBean.setJobDescription("Janitor");
        simpleBean.setName("Mister Jones");

        return simpleBean;

    }
}

public class OXMExample {
    private static final String FILE_NAME = "simplebean.xml";
    private SimpleBean simpleBean;

    private Marshaller marshaller;
    private Unmarshaller unmarshaller;

    public void setMarshaller(Marshaller marshaller) {
        this.marshaller = marshaller;
    }

    public void setUnmarshaller(Unmarshaller unmarshaller) {
        this.unmarshaller = unmarshaller;
    }

    public void saveSimpleBean() throws IOException {
        FileOutputStream os = null;
        try {
            os = new FileOutputStream(FILE_NAME);
            this.marshaller.marshal(simpleBean, new StreamResult(os));
        } finally {
            if (os != null) {
                os.close();
            }
        }
    }

    public void loadSimpleBean() throws IOException {
        FileInputStream is = null;
        try {
            is = new FileInputStream(FILE_NAME);
            this.simpleBean 
                        
= (SimpleBean) this.unmarshaller.unmarshal(new StreamSource(is));
        } finally {
            if (is != null) {
                is.close();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        ApplicationContext appContext 
                        
= new ClassPathXmlApplicationContext("applicationContext.xml");
        OXMExample ex = (OXMExample) appContext.getBean("oxmExample");
        ex.go();
    }

    private void go() throws IOException {
        simpleBean = getSimpleBean();

        saveSimpleBean();
        loadSimpleBean();
        
        System
.out.println("name: " + simpleBean.getName());
        System.out.println("job description: " + simpleBean.getJobDescription());
        System.out.println("age: " + simpleBean.getAge());
        System.out.println("executive: " + simpleBean.isExecutive());
    }


    private SimpleBean getSimpleBean() {
        SimpleBean simpleBean = new SimpleBean();
        simpleBean.setAge(35);
        simpleBean.setExecutive(false);
        simpleBean.setJobDescription("Janitor");
        simpleBean.setName("Mister Jones");

        return simpleBean;

    }
}
 


To explain Listing 2, I'll start with the main method, which is what is executed first, and then follow the code from there.

First, in the main method, your code grabs the Spring application context. This is the configuration file seen in Listing 1. This file must be in the classpath or running the code will generate an exception.

When you obtain the application context, an instance of OXMExample is created from the definition provided in the configuration file. Note that the name of the bean, (oxmExample), is exactly the same in the code as it is defined in the configuration file (Listing 1). After creating an instance of OXMExample, you call the go() method. This is a little unusual in that the Spring framework instantiates an object that is already run from the command line, but that just keeps things simple for the purposes of this demonstration.

The go() method does three things before it prints out result data:

1. It creates an instance of SimpleBean.
2. Then it marshals that instance.
3. Then it unmarshals the XML document created from the marshalling.

You use the getSimpleBean() method to instantiate a SimpleBean object that contains information about a fictional employee. This information includes age (an integer), job description (a string), name (a string), and whether or not the employee is an executive (a Boolean). You populate the fields with test data and the return object back to the caller, in this case the go() method. You write the contents of this bean to an XML file when the marshalling occurs, and then read the contents of that file when the unmarshalling occurs.

The saveSimpleBean() method performs the marshalling. First, you obtain a FileOutputStream object pointing to simplebean.xml. Then, you use the marshaller object (which was instantiated by Spring's dependency injection) to invoke the marshal method. This method requires two parameters:

* The object to be marshalled (in this case, the SimpleBean instance)
* A StreamResult object, which basically represents an XML output abstraction

The loadSimpleBean() method performs the unmarshalling. First, you obtain a FileInputStream object pointing to simplebean.xml. Then, you use the unmarshaller object (which was instantiated by Spring's dependency injection) to invoke the unmarshal method. The only parameter required is a StreamSource object wrapping the FileInputStream object. Note that the unmarshalling creates a generic object, so you must explicitly cast it to the SimpleBean type.

Even with the class and the Spring configuration file in place, you're not quite ready to run this code yet. Remember the mapping file from Listing 1? You still need to define that. It is shown in Listing 3 and, once again, must be in the classpath at runtime.

Listing 3. The mapping.xml file

CODE: تحديد الكل
<mapping>
        <class name="com.xyz.SimpleBean">

           <map-to xml="simplebean"/>

           <field name="age" type="integer">
              <bind-xml name="age" node="element"/>
           </field>

           <field name="executive" type="boolean">
              <bind-xml name="is-executive" node="element"/>
           </field>
       
           
<field name="jobDescription" type="string">
              <bind-xml name="job" node="element"/>
           </field>

           <field name="name" type="string">
              <bind-xml name="name" node="element"/>
           </field>
        </class>
</
mapping>
<
mapping>
        <class name="com.xyz.SimpleBean">

           <map-to xml="simplebean"/>

           <field name="age" type="integer">
              <bind-xml name="age" node="element"/>
           </field>

           <field name="executive" type="boolean">
              <bind-xml name="is-executive" node="element"/>
           </field>
       
           
<field name="jobDescription" type="string">
              <bind-xml name="job" node="element"/>
           </field>

           <field name="name" type="string">
              <bind-xml name="name" node="element"/>
           </field>
        </class>
</
mapping>
 


The mapping file in Listing 3 is specific to the Castor implementation of O/X mapping. The first element (class) simply defines the class that is to be mapped to an XML output. You must specify the full path.

The map-to element gives the name of the root element for the XML file. This is important because the XML specification mandates that each XML file must have a root element.

Each field element is mapped to a specific field in the SimpleBean class. The bind-xml child element for each field element is used to specify XML-specific information about the field, such as the name of the corresponding XML element and whether the value of each field should be an element value or an attribute value. As you can see, in this case all values are element values.

Testing it

Although the coding is done, you must resolve certain dependencies before you execute this application.

The Spring-specific dependencies are:

* org.springframework.asm-3.0.0.M4.jar
* org.springframework.beans-3.0.0.M4.jar
* org.springframework.context-3.0.0.M4.jar
* org.springframework.core-3.0.0.M4.jar
* org.springframework.expression-3.0.0.M4.jar
* org.springframework.oxm-3.0.0.M4.jar

The Castor-specific dependencies are:

* castor-1.3-core.jar
* castor-1.3-xml.jar

You also need commons-logging-1.1.1.jar and log4j-1.2.15.jar because they are required by the Spring framework.

All of these Java Archive (JAR) files must be in the classpath at runtime. If you try to execute the code without these dependencies, you will likely receive an exception that a certain class cannot be found. If that is the case, simply double-check your classpath to ensure that all of the required dependencies are in place. In fact, you need most of the JAR files to successfully compile the code. For information about obtaining these JAR files, see Resources at the end of this article.

You can use your favorite IDE or simply use the command line to run OXMExample.class. To run it from the command line, simply type java -cp [classpath] OXMExample from your working directory, where [classpath] is the classpath pointing to all of the dependencies (JAR files and configuration files) mentioned previously.

After you run it for the first time, a new file called simplebean.xml should appear in your current working directory. The contents of that file should match Listing 4.

Listing 4. The simplebean.xml file

CODE: تحديد الكل
<?xml version="1.0" encoding="UTF-8"?>
<simplebean>
 <age>35</age>
 <is-executive>false</is-executive>
 <job>Janitor</job>
 <name>Mister Jones</name>
</simplebean>
<?xml version="1.0" encoding="UTF-8"?>
<simplebean>
 <age>35</age>
 <is-executive>false</is-executive>
 <job>Janitor</job>
 <name>Mister Jones</name>
</simplebean>


While Listing 4 presents you with output from the marshalling side of the application, you should also see results from the unmarshalling side of the application in your console. That should look like Listing 5.

Listing 5. Unmarshalling output

name: Mister Jones
job description: Janitor
age: 35
executive: false


And there you have it. You have successfully completed your first Spring O/X mapping test. Congratulations!

Now it's time to do what developers do best: Tinker with the code. Add fields to the class and map them to the XML file. Take some fields away and remove them from the XML file. Refer to the Castor documentation and try to do more complicated things, such as nested elements. Your possibilities are endless.

Conclusion

Spring's O/X mapping interface is a powerful addition to the Spring framework. Using it, you can translate XML documents into Java objects and you can also translate Java objects into XML documents.

It leverages one of the key advantages of Spring: dependency injection. Using dependency injection together with Spring's O/X Mapper, you can easily develop a solution using any one of a variety of O/X implementations such Castor, XBeans, JiBX, JAXB, and XStream. Because the specific implementation is part of Spring's powerful Inversion of Control container, developers can easily switch between specific O/X implementations without making code changes.

Spring's O/X Mapper also provides developers with a consistent exception hierarchy. This means that no matter which third-party implementation you select, the runtime exceptions thrown are the same. Once again, this facilitates changing between O/X vendors.

Given the high demand of Java applications requiring XML support and the heavy use of the Spring framework throughout the Java development community, the Spring O/X Mapper is a welcome addition for Java application developers worldwide.

[/align]
ref : http://www.ibm.com/developerworks/library/x-springXOM/

من أهم إنجازات الحكومة نجاحها في توحيد المصريين بمختلف انتماءاتهم على كلمة واحدة .. حسبي الله ونعم الوكيل

Regards,

Amr Salah El-Hanbaly
Software Developer
Professional Services
Asset Technology Group

CELL: +2 010 7597043
Amr Salah Website

صورة العضو الشخصية
amrSalah
حاسوباتى
حاسوباتى
 
مشاركات: 43
اشترك في: الأربعاء سبتمبر 26, 2007 1:48 am
أعطى: 20 شكر
أخذ: 94 شكر
الحالة الحاسوباتية: خريج (علوم الحاسب)

 

 

العودة إلى منتدى JAVA

الموجودون الآن

المستخدمون المتصفحون لهذا المنتدى: لا يوجد أعضاء مسجلين متصلين و 1 زائر