2010-10-08 55 views
1

我正在开发一个'用户设置portlet',用户可以在其中影响多个其他portlet的搜索行为。我想这样做的方式是通过共享bean。所有Portlet都处于不同的战争中,我宁愿避免在单耳中使用所有战争并使用父应用程序上下文,因此portlet的部署可以自主进行,但没有太多运气可以找到有关如何做到这一点。单独的war文件中的portlet之间的共享bean

我按照this blog post尝试部署在他们的战争EAR文件,但几个小时摔跤后,我特地没有接近解决我的问题......

的目录结构看起来是这样的:

 
portlets 
|--- ear 
| \--- src/main/application/META-INF/application.xml 
| 
|--- jar (contains UserSettings.java) 
| \--- src/main/resources/beanRefContext.xml 
| \--- src/main/resources/services-context.xml 
| \--- src/main/java/com/foo/application/UserSettings.java 
| 
|--- messagehistory (war, portlet 1) 
| \--- [...] 
| 
|--- settings (war, portlet 2) 
| \--- [...] 
| 
\--- pom.xml 

我试过设置scope="session"类似如下:

<bean id="userSettings" class="com.foo.application.UserSettings" scope="session"> 
    <aop:scoped-proxy /> 
</bean> 

但是当我部署的耳朵,我得到java.lang.IllegalStateException: No Scope registered for scope 'session'

这是历史记录 portlet的控制器,用户可以通过设置portlet的限制来搜索消息历史记录。 设置 portlet的控制器是相同的。


package com.foo; 

import javax.portlet.ActionRequest; 
import javax.portlet.ActionResponse; 
import javax.portlet.PortletSession; 
import javax.servlet.ServletContext; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.ui.Model; 
import org.springframework.validation.BindingResult; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.SessionAttributes; 
import org.springframework.web.bind.support.SessionStatus; 
import org.springframework.web.portlet.bind.annotation.ActionMapping; 

import com.foo.application.UserSettings; 
import javax.annotation.PostConstruct; 
import org.springframework.context.ApplicationContext; 
import org.springframework.web.context.ContextLoader; 
import org.springframework.web.context.ServletContextAware; 

@Controller 
@SessionAttributes({"searchQuery", "searchResults"}) 
@RequestMapping("VIEW") 
public class ViewHistory extends ContextLoader implements ServletContextAware { 
    private UserSettings userSettings; 
    private ServletContext servletContext; 

    @Override 
    public void setServletContext(ServletContext servletContext) { 
     this.servletContext = servletContext; 
    } 

    @PostConstruct 
    public void init() { 
     ApplicationContext ctx = loadParentContext(servletContext); 
     servletContext.setAttribute(LOCATOR_FACTORY_KEY_PARAM, "ear.context"); 
     userSettings = (UserSettings) ctx.getBean("userSettings"); 
    } 

    @ModelAttribute("userSettings") 
    public UserSettings createUserSettings(Model model) { 
     model.addAttribute(userSettings); 
    } 

    @RequestMapping 
    public String doSearch(Model model, PortletSession portletSession) { 
     return "view"; 
    } 

    @ActionMapping(params = "action=search") 
    public void searchAction(
      Model model, 
      ActionRequest request, ActionResponse response, 
      BindingResult bindingResult, SessionStatus status) 
    { 
     // do nothing 
    } 
} 

web.xml文件两场战争(它们是相同的)看起来像这样:

<?xml version="1.0" encoding="UTF-8"?> 
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 

    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/applicationContext.xml</param-value> 
    </context-param> 

    <context-param> 
     <param-name>parentContextKey</param-name> 
     <param-value>ear.context</param-value> 
    </context-param> 

    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
    <listener> 
     <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> 
    </listener> 

    <filter> 
     <filter-name>springFilter</filter-name> 
     <filter-class> 
      org.springframework.web.filter.RequestContextFilter 
     </filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>springFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

    <servlet> 
     <servlet-name>dispatcher</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <load-on-startup>2</load-on-startup> 
    </servlet> 
    <servlet> 
     <servlet-name>ViewRendererServlet</servlet-name> 
     <servlet-class>org.springframework.web.servlet.ViewRendererServlet</servlet-class> 
    </servlet> 

    <servlet-mapping> 
     <servlet-name>dispatcher</servlet-name> 
     <url-pattern>*.htm</url-pattern> 
    </servlet-mapping> 
    <servlet-mapping> 
     <servlet-name>ViewRendererServlet</servlet-name> 
     <url-pattern>/WEB-INF/servlet/view</url-pattern> 
    </servlet-mapping> 
    <session-config> 
     <session-timeout>30</session-timeout> 
    </session-config> 
    <welcome-file-list> 
     <welcome-file>index.jsp</welcome-file> 
    </welcome-file-list> 
</web-app> 

回答

0

原来这是很容易只使用Spring的@EventMapping标注为纯JSR 286事件触发。不需要耳朵,也不需要父应用程序环境。我只需要在单独的jar项目中将我的UserSettings.java包括在内,并将其作为对war的依赖项。

search的portlet控制器看起来是这样的:


package com.foo; 

import com.foo.event.UserSettings; 
import javax.portlet.ActionRequest; 
import javax.portlet.ActionResponse; 
import javax.portlet.EventRequest; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.ui.Model; 
import org.springframework.validation.BindingResult; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.SessionAttributes; 
import org.springframework.web.bind.support.SessionStatus; 
import org.springframework.web.portlet.bind.annotation.ActionMapping; 

import javax.portlet.Event; 
import org.springframework.web.bind.annotation.ModelAttribute; 
import org.springframework.web.portlet.bind.annotation.EventMapping; 

@Controller 
@RequestMapping("VIEW") 
public class ViewHistory { 
    private UserSettings userSettings = new UserSettings(); 

    @ModelAttribute("userSettings") 
    public UserSettings createUserSettings(Model model) { 
     return userSettings; 
    } 

    @RequestMapping 
    public String doSearch(Model model) { 
     return "view"; 
    } 

    @ActionMapping(params = "action=search") 
    public void searchAction(
      Model model, 
      ActionRequest request, ActionResponse response, 
      @ModelAttribute("userSettings") UserSettings userSettings, 
      BindingResult bindingResult, SessionStatus status) 
    { 
     // do something 
    } 

    /** 
    * Spring calls this whenever an event is received. 
    * Can be limited to certain event. 
    */ 
    @EventMapping 
    public void handleEvent(EventRequest request) { 
     Event event = request.getEvent(); 

     if (event.getName().equals("UserSettings")) { 
      userSettings = (UserSettings)event.getValue(); 
     } 
    } 
} 

...并为settings门户:


package com.foo; 

import com.foo.event.UserSettings; 
import javax.portlet.ActionRequest; 
import javax.portlet.ActionResponse; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.ui.Model; 
import org.springframework.validation.BindingResult; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.SessionAttributes; 
import org.springframework.web.bind.support.SessionStatus; 
import org.springframework.web.portlet.bind.annotation.ActionMapping; 

import javax.xml.namespace.QName; 
import org.springframework.web.bind.annotation.ModelAttribute; 

@Controller 
@RequestMapping("VIEW") 
public class ViewSettings { 
    private QName qname = new QName("http:foo.com/usersettings", "UserSettings"); 

    @ModelAttribute 
    public UserSettings createUserSettings(Model model) { 
     return new UserSettings(); 
    } 

    @ActionMapping(params = "action=search") 
    public void searchAction(
      Model model, 
      ActionRequest request, ActionResponse response, 
      @ModelAttribute("userSettings") UserSettings userSettings, 
      BindingResult bindingResult, SessionStatus status) 
    { 
     // as soon as an action is triggered (save button is pressed or 
     // whatever), send the modified UserSettings instance as an 
     // event to the search portlet (actually any portlet, but I 
     // only have one that will read events). 
     response.setEvent(qname, userSettings); 
    } 

    @RequestMapping 
    public String doView(Model model) { 
     return "view"; 
    } 
} 
相关问题