4

I am trying to convert a static xml into a POJO (unmarshalling) in my controller class. I am using Jaxb2Marshaller and I am configuring in the following way in my root context

<oxm:jaxb2-marshaller id="marshaller">
    <oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Airport"/>        
</oxm:jaxb2-marshaller>

I am trying to inject the marshaller using autowiring. But it throws No Bean Found Exception.

@AutoWired
private Unmarshaller marshaller;

How to inject the marshaller in the controller. Any other ways or pointing out the error in my code will be helpful?

karthik
  • 463
  • 1
  • 6
  • 16

2 Answers2

2

I faced a similar issue recently, and I believe the solution I come up is different from the accepted answer, which I think it worth to raise it for reference.

Let me make sure my understanding on your situation is right:

In dispatcher-context, you have:

  1. created the jaxb2 marshaller
  2. created the controllers.
  3. in one of the controller, you tried to inject the marshaller (through annotation)

However the injection failed. And when move the creation of JAXB2 Marshaller to the root context, it works.

If my description of your situation is right, then keep on reading:


What you have done is in fact correct: JAXB2 Marshaller and the Controller beans are created in the same context (the dispatcher-context) and Controller bean should be able to be injected with the marshaller bean.

The problem is possibly in the root context, you have created another controller bean. And it is that extra controller bean in root context cannot be injected with the marshaller (because marshaller bean exists in a child context which cannot be accessed). Therefore when you move the marshaller bean to root context, everything seems work (because both Controller in root context and dispatcher context can see the marshaller bean)

The common problem is in your root context xml, you have component-scan declared. By default, component-scan will include classes annotated with @Controller during its scan. This bring another controller bean in your root context.

If it is the case, solution is straight-forward: simply exclude Controller in root context component scan (and include only Controller in dispatcher context component scan)

root context xml:

<context:component-scan base-package="com.foo">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

dispatcher context xml:

<context:component-scan base-package="com.foo" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
1

Spring context configuration

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
        xmlns:automation="http://www.springframework.org/schema/automation"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:oxm="http://www.springframework.org/schema/oxm"
        xmlns:task="http://www.springframework.org/schema/task"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/util 
                            http://www.springframework.org/schema/util/spring-util.xsd
                            http://www.springframework.org/schema/context 
                            http://www.springframework.org/schema/context/spring-context.xsd
                            http://www.springframework.org/schema/automation
                            http://www.springframework.org/schema/automation/automation.xsd
                            http://www.springframework.org/schema/task 
                            http://www.springframework.org/schema/task/spring-task.xsd
                            http://www.springframework.org/schema/oxm
                            http://www.springframework.org/schema/oxm/spring-oxm.xsd">

        <context:annotation-config/>

        <oxm:jaxb2-marshaller id="jaxb2Marshaller">
            <oxm:class-to-be-bound name="your.package.Prova" />
        </oxm:jaxb2-marshaller>

    </beans>

Class

@AutoWired
private org.springframework.oxm.Unmarshaller jaxb2Marshaller;
tmarwen
  • 15,750
  • 5
  • 43
  • 62
Xstian
  • 8,184
  • 10
  • 42
  • 72
  • Thanks for the answer It works But Why it does not work if i configure in the dispatcher-servlet.xml (i mean in the context of the servlet)? – karthik Sep 13 '14 at 07:45
  • I think that you should see this [link](http://stackoverflow.com/a/16458969/3364187) – Xstian Sep 13 '14 at 12:41
  • One thing that I am not clear: the dispatcher-servlet.xml is going to create a separate spring app context (which I believe is a child context of the main one), and in this dispatcher context, the jaxb2marshaller and the controller are created. They are all in the same context but why can't the jaxb2marshaller be injected? – Adrian Shum Nov 24 '14 at 02:27
  • The `applicationContext.xml` defines the beans for the "root webapp context", i.e. the context associated with the webapp. The `dispatcher-servlet.xml` (or whatever else you call it) defines the beans for one servlet's app context. – Xstian Nov 24 '14 at 08:54
  • That's what I understand. And I believe what you are suggesting is in fact wrong: we shouldn't put dispatcher-related config (jaxb2 marshaller) in the root context. It should be put in the dispatcher context instead. The reason for No Bean Found Exception is caused by another issue (which I have added another answer for) – Adrian Shum Nov 24 '14 at 08:59
  • Some extra explanation why I think your suggestion is wrong. We should be aware that there are 2 app context, one root, and one child context for servlet. Controllers and the JAXB2Marshaller are both supposed to be created in the servlet context. Hence there should be no reason that we cannot inject the JAXB2Marshaller to the Controllers because they both exists in the child context. – Adrian Shum Nov 25 '14 at 01:34