Is there a built-in Spring environment variable for the web context root?
Asked Answered
M

4

12

I'm using Spring Web Services to expose a service as a web service. In my spring configuration xml file, I have a bean which is an instance of DefaultWsdl11Definition. One of the properties that needs to be set is the locationUri. This needs to be a fully qualified Uri, but I don't want to have to change this value when the application gets promoted from dev to uat and to production. Spring knows what the web application context root is, so is there a variable that I can specify in my configuration file to access it?

Something like:

<bean id="myWebServices"
    class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
    <property name="schemaCollection">
        <bean
            class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">
            <property name="xsds" ref="xsdList"/>
            <property name="inline" value="true" />
        </bean>
    </property>
    <property name="portTypeName" value="myWebServices" />
    <property name="locationUri" value="${webContextRoot}/webServices" />
</bean>
Mastoiditis answered 3/8, 2011 at 18:45 Comment(0)
A
9

With Spring 3.0, you should be able to access the servlet context through the servletContext bean in the web application context:

<property name="locationUri" value="#{servletContext.contextPath}/webServices" />

If you're using pre-Spring-EL (before 3.0), you should be able to do

<bean name="servletContextBean" class="org.springframework.web.context.support.ServletContextFactoryBean" />
<bean name="contextPath" factory-bean="servletContextBean" factory-method="getContextPath" />
<bean name="locationUri" factory-bean="contextPath" factory-method="concat">
   <constructor-arg value="/webServices" />
</bean>

and inside your myWebservices bean

<property name="locationUri" ref="locationUri" />

EDIT:

I don't think getting the server name and port from the ServletContext, as depending on the setup the web container may not know the hostname (i.e. a HTTP server may be in front of the web container, e.g. tomcat may be behind an Apache web server or depending on the Websphere configuration).

However, the following may be part of a solution to get the hostname. With Spring 3.0, you could do the following:

<property name="host" 
          class="java.net.InetAddress" 
          factory-method="getLocalHost"/>

<property name="locationUri" 
          value="http://#{host.canonicalHostName}:8080/#{servletContext.contextPath}/webServices" />
Ademption answered 3/8, 2011 at 23:58 Comment(5)
This is really close. Unfortunately, contextPath only gives me the relative path without the protocol, server, and port. Is there a way to get the full path to the contextPath? Also I don't see getContextPath() on the ServletContextFactoryBean in the api docs. Where do I get the list of methods?Mastoiditis
The ServletContextFactoryBean will return an instance of the ServletContext (download.oracle.com/javaee/6/api/javax/servlet/…).Ademption
Added possible solution for getting the hostname on startup.Ademption
Yeah, I figured out that ServletContextFactoryBean returned an instance of the ServletContext after some more digging. So I attempted to use the ServletContext.getRealPath(String path) method, but for some reason it is returning null. I'll keep at it. Thanks for the idea of using Spring factory methods.Mastoiditis
getRealPath gets you the path of a resource on the local filesystem, rather than a URL. The only way to get the servername and port would be through the getRequestURL() method of the HttpServletRequest, but I guess that won't help as you won't have a request on startup.Ademption
V
3

I had a similar problem that you described, I use property files to do this

  • ws_dev.properties
  • ws_prod.properties

I configured my property file like this, The deployment property is java vm argument like

-Ddeployment=dev

<context:property-placeholder location="ws_${deployment}.properties"/>
Vines answered 3/8, 2011 at 19:40 Comment(0)
S
2

May be late, but may some other need a solution too:

set property in servlet:

web.xml

<servlet>
<servlet-name>spring-ws</servlet-name>
    <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/spring-ws-context.xml</param-value>
    </init-param>
    <init-param>
        <param-name>transformWsdlLocations</param-name>
        <param-value>true</param-value>
    </init-param>
</servlet>

The bean declaration in spring-ws-context.xml:

<bean id="WebService"
    class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition"
    p:portTypeName="App" p:locationUri="/WebServices" p:requestSuffix="Request"
    p:responseSuffix="Response">
    <property name="schema">
        <bean class="org.springframework.xml.xsd.SimpleXsdSchema" p:xsd="classpath:/requestTypes.xsd" />
    </property>
</bean>
Shipmate answered 24/9, 2013 at 22:17 Comment(0)
C
-1

You can add ApplicationContextAware interface to your bean, cast it to WebApplicationContext and then get ServletContext. Also see class org.springframework.web.context.ContextLoader

Crymotherapy answered 3/8, 2011 at 18:55 Comment(1)
That might work, but the bean he is instantiating is a spring bean, not one of his own creation so then he would have to extend it etc. If he is going to do it with his own bean, couldn't he just inject the ApplicationContext (or WebApplicationContext) with a Resource annotation instead? then there's no interface implementation that needs to occur. Obviously that solution relies on him being in a version of spring that supports the Resource annotation.Milker

© 2022 - 2024 — McMap. All rights reserved.