Announcement Announcement Module
Collapse
No announcement yet.
PropertyPlaceholder for property keys? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • PropertyPlaceholder for property keys?

    Hi there,

    is it possible to use PropertyPlaceholder for property keys, e.g. I want to use something like this in my application-servlet.xml:
    Code:
    	<bean id="urlMapping"
    		class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    		<property name="interceptors">
    			<list>
    				<ref bean="authorizationInterceptor"/>
    			</list>
    		</property>
    		<property name="mappings">
    			<props>
    				<prop key="${view.mapping.url.logout}">logoutController</prop>
    			</props>
    		</property>
    	</bean>
    I know that it is working it I would have something like this

    Code:
    <prop key="/logout.htm">${view.mapping.controller.logout}</prop>
    But as I want to externalize the mapping urls in order to beeing able to access them from my Java code through a MessageResource too. Or is there another way of doing it?

    Thanks for your kind help.

    Dominik

  • #2
    As far as I can tell, the existing placeholders do replace the values of keys and values (see BeanDefinitionVisitor.visitMap). But what you are trying to do, reading between the lines, goes a little further. URLs like "/logout.htm" are often MVC Controller bean names. The bean names will have to be static (the BeanFactory does not support changing the bean names), so there is a danger that you have duplication of the keys - one set in property files for the placeholder, and an identical one in the bean factory definition to identify the Controller.

    Is that an accurate assessment (I'm guessing here)?

    Comment


    • #3
      Thanks David for your reply.

      I didn't know that string like '/logout.htm' were handled internally by spring as the bean names for the controller. In my beans xml I declared my controleller as logoutController and thus am referencing to it

      Code:
      <props>
      				<prop key="${view.mapping.url.logout}">logoutController</prop>
      </props>
      So I don't have any plans to change the logoutController bean name nor reference that from a properties file. So I'm wondering if I'm confused by reasoning that way and thinking that logoutController is the bean name for my controller and not '/logout.htm'.

      And what could in any case be a solution to reference the .htm-urls defined in the beans xml from java code?

      Thanks for your kind help, David.

      Dominik

      Comment


      • #4
        I think it is me that is confused. Who is the consumer of your URL map? It is conventional to give Controllers the bean name="/<url>" (as in all the sample apps), and to leave their id empty. The name can then be used by the BeanFactory in place of an id. So the map you are constructing *might* be redundant. It's hard to say from what you have posted.

        In any case, are you saying you have tried using the PropertiesPlaceholderConfigurer and it doesn't work? I think it should work fine, so maybe you have set it up slightly wrong. Or maybe you could help it by making your map a <map> instead of a <properties> - although I can't see why that would matter.

        Comment


        • #5
          Hi David,

          thanks again for this fast reply. Ok, I'm relatively new to Spring so that might account to some confusion...

          So this is my servlet beans xml file (excerpt)

          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <!--  - Application context definition for "Auspuffanlagen" DispatcherServlet.  -->
          <beans xmlns="http://www.springframework.org/schema/beans"
          	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          	xmlns:aop="http://www.springframework.org/schema/aop"
          	xmlns:tx="http://www.springframework.org/schema/tx"
          	xsi:schemaLocation="
                 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
                 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
          	
          	<!-- Url Mapping -->
          	<bean id="urlMapping"
          		class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
          		<property name="interceptors">
          			<list>
          				<ref bean="authorizationInterceptor"/>
          				<ref bean="exportInterceptor"/>
          			</list>
          		</property>
          		<property name="mappings">
          			<props>
          				<prop key="/logout.htm">logoutController</prop>
          				<prop key="/auspuffanlage.htm">auspuffanlageController</prop>
          				<prop key="/beschaffung.htm">beschaffungController</prop>
          				<prop key="/beschaffungplanung.htm">
          					beschaffungPlanungController</prop>
          				<prop key="/deleteauspuffanlage.htm">
          					deleteAuspuffanlageController</prop>
          				<prop key="/deletebeschaffungplanung.htm">
          					deleteBeschaffungPlanungController</prop>
          				<prop key="/einsatz.htm">einsatzController</prop>
          				<prop key="/editeinsatz.htm">editEinsatzController</prop>
          				<prop key="/**/*">dwrController</prop>
          			</props>
          		</property>
          		<property name="lazyInitHandlers" value="true"/>
          	</bean>
          	<bean id="viewResolver"
          		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
          		<property name="viewClass">
          			<value>org.springframework.web.servlet.view.JstlView</value>
          		</property>
          		<property name="prefix">
          			<value>WEB-INF/jsp/secure/</value>
          		</property>
          		<property name="suffix">
          			<value>.jsp</value>
          		</property>
          	</bean>
          
          		
          	<!-- Interceptors -->
          	<bean id="authorizationInterceptor" 
          		class="com.bmw.auspuffanlagen.service.interceptor.AuthorizationInterceptor" />
          	<bean id="exportInterceptor" 
          		class="com.bmw.auspuffanlagen.service.interceptor.ExportInterceptor" />
          
          	<bean id="exceptionHandler" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
          		<property name="exceptionMappings">
          			<props>
          				<prop key="java.lang.Exception">exception_error</prop>
          				<prop key="com.bmw.auspuffanlagen.exception.NoLogonPermissionException">
          					exception_nologon_permission</prop>
          				<prop key="com.bmw.auspuffanlagen.exception.NoAuspuffanlageDefinitionPermissionException">
          					exception_noauspuffanlagedefinition_permission</prop>
          			</props>
          		</property>
          	</bean>
          	
          	<!-- Web Controller -->
          	<bean id="auspuffanlageController"
          		class="com.bmw.auspuffanlagen.view.AuspuffanlageController"
          		parent="suchFilterFormController" scope="session">
          		<aop:scoped-proxy/>
          		<property name="validator" ref="validatorAuspuffanlageDefinition"/>
          		<property name="formView" value="auspuffanlagedefinition"/>
          		<property name="successView" value="auspuffanlage.htm"/>
          		<property name="commandName" value="cmdAuspuffanlageDefinition"/>
          		<property name="commandClass"
          			value="com.bmw.auspuffanlagen.view.cmd.CmdAuspuffanlageDefinition"/>
          		<property name="auspuffanlageTableAssembler"
          			ref="auspuffanlageTableAssembler"/>
          		<property name="auspuffanlagenManager" ref="auspuffanlagenMan"/>
          	</bean>
          	<bean id="beschaffungController"
          		class="com.bmw.auspuffanlagen.view.BeschaffungController"
          		parent="suchFilterFormController" scope="session">
          		<aop:scoped-proxy/>
          		<property name="formView" value="uebersichtbeschaffung"/>
          		<property name="successView" value="beschaffung.htm"/>
          		<property name="commandName" value="cmdBeschaffung"/>
          		<property name="commandClass"
          			value="com.bmw.auspuffanlagen.view.cmd.CmdBeschaffung"/>
          		<property name="beschaffungTableAssembler"
          			ref="beschaffungTableAssembler"/>
          		<property name="beschaffungManager" ref="beschaffungMan"/>
          	</bean>
          	<bean id="beschaffungPlanungController"
          		class="com.bmw.auspuffanlagen.view.BeschaffungPlanungController"
          		parent="suchFilterFormController" scope="session">
          		<aop:scoped-proxy/>
          		<property name="validator" ref="validatorBeschaffungPlanung"/>
          		<property name="formView" value="uebersichtbeschaffungplanung"/>
          		<property name="successView" value="beschaffungplanung.htm"/>
          		<property name="commandName" value="cmdBeschaffungPlanung"/>
          		<property name="commandClass"
          			value="com.bmw.auspuffanlagen.view.cmd.CmdBeschaffungPlanung"/>
          		<property name="beschaffungPlanungTableAssembler"
          			ref="beschaffungPlanungTableAssembler"/>
          		<property name="beschaffungManager" ref="beschaffungMan"/>
          	</bean>
          	<bean id="deleteAuspuffanlageController"
          		class="com.bmw.auspuffanlagen.view.DeleteAuspuffanlageController">
          		<property name="successView" value="auspuffanlage.htm"/>
          		<property name="auspuffanlagenManager" ref="auspuffanlagenMan"/>
          	</bean>
          	<bean id="deleteBeschaffungPlanungController"
          		class="com.bmw.auspuffanlagen.view.DeleteBeschaffungPlanungController">
          		<property name="successView" value="beschaffungplanung.htm"/>
          		<property name="beschaffungManager" ref="beschaffungMan"/>
          	</bean>
          	<bean id="logoutController"
          		class="com.bmw.auspuffanlagen.view.LogoutController">
          		<property name="successView" value="logout"/>
          	</bean>
          	<bean id="risspruefungController"
          		class="com.bmw.auspuffanlagen.view.RisspruefungController"
          		scope="session">
          		<aop:scoped-proxy/>
          		<property name="successView" value="risspruefung"/>
          		<property name="schadenManager" ref="schadenMan"/>
          		<property name="risspruefungTableAssembler"
          			ref="risspruefungTableAssembler"/>
          	</bean>
          	<bean id="schadenController"
          		class="com.bmw.auspuffanlagen.view.SchadenController" scope="session">
          		<aop:scoped-proxy/>
          		<property name="successView" value="schaden"/>
          		<property name="schadenManager" ref="schadenMan"/>
          		<property name="schadenTableAssembler" ref="schadenTableAssembler"/>
          	</bean>
          	<bean id="suchFilterFormController" abstract="true"
          		class="com.bmw.auspuffanlagen.view.SuchFilterFormController">
          		<property name="sessionForm" value="false"/>
          		<!--		<property name="validator" ref="defineSuchFilterValidator" />-->
          		<property name="suchFilterManager" ref="suchFilterMan"/>
          	</bean>
          	
          	<!-- Validator -->
          	<bean id="validatorAuspuffanlageDefinition"
          		class="com.bmw.auspuffanlagen.service.validator.ValidatorAuspuffanlageDefinition">
          		<property name="auspuffanlagenManager">
          			<ref bean="auspuffanlagenMan"/>
          		</property>
          	</bean>
          	<bean id="validatorBeschaffungPlanung"
          		class="com.bmw.auspuffanlagen.service.validator.ValidatorBeschaffungPlanung">
          	</bean>
          	
          </beans>
          I'm not sure who is the consumer of my url map, as i don't reference it in my beans xml. I thought that it is handled internally by spring. (I followed the spring tutorial)

          My messageSource and the propertyconfigurer are described in another beans xml file, but which is getting loaded through the contextConfigLocation declaration in the web.xml
          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
          <beans>
          	<bean id="propertyConfigurer"
          		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
          		<property name="locations">
          			<list>
                          <value>classpath:project.properties</value> 
                          <value>classpath:beans.properties</value> 
                      </list>			
          		</property>
          	</bean>
          	
          	<!-- Message Source -->
          	<bean id="messageSource"
          		class="com.bmw.auspuffanlagen.view.MessageSourceHelper">
          		<property name="basenames">
          			<list>
                          <value>/WEB-INF/messages</value> 
                          <value>/WEB-INF/classes/beans</value> 
                      </list>			
          		</property>
          		<property name="cacheSeconds" value="1" />
          	</bean>
          	
          </beans>
          So basically, that's it. The controller property placeholder are defined in beans.properties. I already am using the project.properties and this works fine for declaring parameters of my datasource in the properties file. It just doesn't seem to work for my controllers, as when I point to logout.htm it gets redirected to logout.htm/index.jsp and this page of course doesn't exist. (I think as it can't find a mapping in my url map it goes to the InternalResourceViewResolver which gives back this url then)

          Did I miss something? Should it work like that? Spring doesn't throw any exception or log any warning when I do it through the PropertyPlaceholder, so I'm guessing that it's using my ${...} literally as an url.

          Thanks for your interest and your support.

          Dominik

          Comment


          • #6
            Aha. Now it is becoming clearer, I think. Your beans.properties is in a different ApplicationContext than the URL map. Each servlet is initialised (at different times depending on when it is first used) with its own ApplicationContext, with a shared parent context. Your PropertyPlaceholderConfigurer is in the parent context, so it doesn't apply to the URL map.

            Can you just add a separate PropertyPlaceholderConfigurer in the servlet xml?

            Comment


            • #7
              Thanks David, you're the man!!! That helped and the url is now working even as a propertyplaceholder, but when i add a separate propertyplaceholder to my servlet beans xml

              Code:
              <bean id="propertyConfigurer"
              		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
              		<property name="locations">
              			<list>
                              <value>classpath:beans.properties</value> 
                          </list>			
              		</property>
              	</bean>
              the url stuff works fine, but then my other propertyconfigurer doesn't get loaded and I get an error because a propertyplaceholder in my dao application-context.xml can't be resolved.

              Code:
              	<bean id="propertyConfigurer"
              		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
              		<property name="locations">
              			<list>
                              <value>classpath:project.properties</value> 
                          </list>			
              		</property>
              	</bean>
              I could pack all together in one property file, but i would prefer not to. I tried to give both propertyplaceholder different bean names, but this didn't help either, because only the bean with the id="propertyConfigurer" got read... am I missing something?

              Comment


              • #8
                ok, i just found out, that when i put my propertyconfigurer in my servlet beans xml like this

                Code:
                	<bean id="propertyConfigurer"
                		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                		<property name="locations">
                			<list>
                                <value>classpath:beans.properties</value> 
                                <value>classpath:project.properties</value> 
                            </list>			
                		</property>
                	</bean>
                all is working fine, but how can i understand this? you told that every servlet has it's own application and a shared parent context. So in my case the separate application-dao.xml definitions are in the shared context, right? So that you can't reference the property configurer from the servlet if it's located in the shared parent context, but you can reference from the shared parent context the property configurer defined in the servlet's application context. Is this correct?

                Comment


                • #9
                  I don't think we're getting the whole picture here. Think of it this way: to get placeholders filled in you don't "reference" the propertyConfigurer, the propertyConfigurer does something to all the beans in *its* own context. It's a push, not a pull.

                  The two application contexts (parent-child) are disconnected from the point of view of BeanFactoryPostProcessor processing, like the placeholder configurer. But the child context (the one belonging to the servlet) can reference beans in its parent.

                  Any placeholders in the servlet context need to be resolved in the properties that the child BeanFactoryPostProcessor has access to. Similarly, any placeholders in the main application context need to be resolved in the properties that the parent BeanFactoryPostProcessor has access to.

                  Comment

                  Working...
                  X