Wiring a web service

I’m dabbling in web services setup, not really knowing what I’m doing yet, and here’s a situation I encountered today:

I was taking a prior example where the web service setup had been done for me, and adapting it for use with a new prototype. I had a WEB-INF/services.xml that looked like this:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:amq="http://activemq.org/config/1.0" xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
		http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
		http://activemq.org/config/1.0 http://activemq.apache.org/schema/core/activemq-core-5.0.0.xsd"

	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

	<jaxws:endpoint id="myGreetingSvcEndpoint" implementor="#myGreetingSvc" address="/GreetingSvc" />

	<bean id="greetingSvc" class="com.example.svc.GreetingSvcImpl">
<property name="messageSender" ref="messageSender" />

When I tried deploying this though, it was looking for a myGreetingSvc bean and couldn’t find it:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myGreetingSvcEndpoint': Cannot resolve reference to bean 'myGreetingSvc' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myGreetingSvc' is defined
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myGreetingSvc' is defined

Why would it be looking for a myGreetingSvc bean?  It seems that the implementor attribute of the jaxws:endpoint expects to reference a bean — replacing “#myGreetingSvc” with “#greetingSvc” on line 14 in services.xml (and correcting my @WebService annotation’s endpointInterface property in GreetingSvcImpl.java to match the name of the interface it was trying to point to) got it working.

I think a lot of how our service.xml is set up (how it’s Spring-like) is because we’re also using CXF, which I hear is Spring-aware.  There’s a lot I still don’t know about web services!

Oh, for a carburetor

I did want to document what solved my latest issue.

Yesterday’s Basic Mistake

In the last day or so I had been trying to get a JMS message producer hooked up to the web method entry point in my test application, so that a SOAP request coming in could kick off the writing of a JMS message to the queue, and then the listener could do the database writing (up to this point I didn’t have a message producer so you had to put messages in the JMS queue manually, using the ActiveMQ console).

I had set up my Spring beans like this:

    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="queueConnectionFactory" />
    <bean id="messageSender" class="com.ontsys.dmn.MessageSender">
<property name="jmsTemplate" ref="jmsTemplate" />
<property name="queueName" value="${com.ontsys.xa.example.queue.name}"/>

But in my web service class, I had made the mistake of instantiating a new MessageSender myself instead of having it injected — and then I wondered why the MessageSender’s jmsTemplate was null!

This Time Was Different

I tried to correct yesterday’s mistake by creating a bean definition for MySimpleServiceImpl like I have in the past when this type of thing happens, to inject MySimpleServiceImpl with the messageSender:

    <bean id="serviceImpl" class="com.ontsys.service.MySimpleServiceImpl">
<property name="messageSender" ref="messageSender" />

But I still got the NullPointerException.  What could it be?!

CXF, and an easy solution

Keith helped me see that the MySimpleServiceImpl class was already a Spring bean in the WEB-INF/services.xml Spring bean file which was already being deployed as part of my project.  I simply needed to remove the duplicate MySimpleServiceImpl bean definition from my applicationContext.xml and add the messageSender reference to the existing bean definition in WEB-INF/services.xml (we have autowiring turned off at the moment, in this test project anyway)… and then it worked!

The WEB-INF/{services.xml,web.xml} files really haven’t been on my radar up to this point. Maybe they will be now!

*Title: If you have a carburetor, you can avoid the problems of [fuel] injection, right? (Just joking around after multiple issues involving my (accidental non-) use of dependency injection.)