Patrick
Patrick

Reputation: 12734

How to migrate Spring Config XML to Spring Boot annotations

I am using Spring boot to create an application for XML marshalling. I followed some tutorials to start the application. I want to avoid any Spring config using xml binding file and want to use annotations instead.

I'm not sure how to migrate this configuration file into annotation driven application.

 <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/beans/spring-beans-3.0.xsd">
  <bean id="XMLConverter" class="com.java2s.common.XMLConverter">
    <property name="marshaller" ref="castorMarshaller" />
    <property name="unmarshaller" ref="castorMarshaller" />
  </bean>
  <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" />
</beans>

At the moment I have written this code:

@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan
@Configuration
public class Application implements CommandLineRunner{

    private static final String XML_FILE_NAME = "whitelist.xml";

    @Autowired
    XMLConverter converter;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... arg0) throws Exception {
        Whitelist whitelist = new Whitelist("example");
        converter.convertFromObjectToXML(whitelist, XML_FILE_NAME);
    }
}

And this:

import javax.xml.transform.stream.StreamResult;

import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.Marshaller;

@Configuration
public class XMLConverter {


    private Marshaller marshaller;

    public Marshaller getMarshaller() {
        return marshaller;
    }

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

    public void convertFromObjectToXML(Object object, String filepath) throws IOException{

        FileOutputStream fileOutputStream = null;
        try{
            fileOutputStream = new FileOutputStream(filepath);
            getMarshaller().marshal(object, new StreamResult(fileOutputStream));
        }finally {
            if(fileOutputStream != null) {
                fileOutputStream.close();
            }
        }
    }
}

I get a Nullpointer at getMarshaller().marshal(object, new StreamResult(fileOutputStream)); because marshaller is null.

In the config file there is the reference to the CastorMarshaller class and to the marshaller property.

How can I migrate this in to an annotation driven application?

Thanks for your help.

EDIT1:

<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" >
    <property name="mappingLocation" value="classpath:mapping.xml" />
</bean>

Upvotes: 2

Views: 9899

Answers (3)

hotzst
hotzst

Reputation: 7496

First off: The @Configuration annotation should be used for on the class that defines the Java Configuration of you application context which is normally a separate file. Instead annotate your classes with @Component:

@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan
@Component
public class Application implements CommandLineRunner{
...

In addition in your XML convertor class the marshaller must be annotated, so it can be wired with the bean definition: @Configuration

public class XMLConverter {

    @Autowired
    private Marshaller marshaller;
...

And finally you need an application context class:

@Configuration
public class ApplicationContext {
    @Bean
    public CastorMarshaller castorMarshaller() {
        return new CastorMarshaller();
    }

    @Bean
    public XMLConverter XMLConverter() {
        XMLConverter convertor = new XMLConverter();
        CastorMarshaller marshaller = castorMarshaller();
        convertor.setMarshaller(marshaller);
        convertor.setUnmarshaller(marshaller);
    }
}

And change the code in your application main method to:

SpringApplication.run(ApplicationContext .class, args);

EDIT: CastorMarhsaller with mappingLocation

   @Bean
    public CastorMarshaller castorMarshaller() {
        ClassPathContextResource resource = new ClassPathContextResource("mapping.xml", getClass().getClassLoader());
        CastorMarshaller marshaller = new CastorMarshaller();
        marshaller.setMappingLocation(resource);
        return marshaller;
    }

If the same resource is also used elsewhere you can define it as bean instead and reuse it, in a similar fashion as shown above.

Upvotes: 1

luboskrnac
luboskrnac

Reputation: 24561

Change first main class this way:

@SpringBootApplication
public class Application{
    public static void main(String[] args) {
        ConfigurableApplicationContext context =
            SpringApplication.run(Application.class, args);

        XMLConverter converter = context.getBean(XMLConverter.class)
        Whitelist whitelist = new Whitelist("example");
        converter.convertFromObjectToXML(whitelist, XML_FILE_NAME);
    }

    @Bean
    public XMLConverter xmlConverter(){
        XMLConverter converter = new XMLConverter();
        CastorMarshaller castorMarshaller = new CastorMarshaller()
        converter.setMarshaller(castorMarshaller);
        converter.setUnmarshaller(castorMarshaller);
        return converter;
    }
}

Beacuse:

  1. @SpringBootApplication uses auto-configuration + component scan
  2. You shouldn't annotate @Configuraition classes with @Component
  3. You don't use command line parameters
  4. Don't understand attempt to create custom converter

Upvotes: 2

Ramon Pires
Ramon Pires

Reputation: 1

You should put @Autowired over private Marshaller marshaller; at XMLConverter class:
@Autowired private Marshaller marshaller;

Upvotes: 0

Related Questions