Announcement Announcement Module
Collapse
No announcement yet.
HttpInvoker without web container? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • HttpInvoker without web container?

    I'm wondering, is it possible to embed httpinvoker in a standalone application without using a web container such as tomcat? If I'm exposing just web services and I want the application to stay in the background (windows service) and use as little memory as possibile, would it be possible to embed servlet support?
    Do you have any experience on this? Can you point to some library that can be used to embed an httpinvoker like described?

  • #2
    HTTP Invoker is designed to site behind the Spring servlet infrastructure so you can't really use it without that in place. HTTP Invoker relies on the infrastructure provided by the servlet container for HTTP communication. You might want to look at Jetty for a small, embeddable servlet container to solve this problem.

    Rob

    Comment


    • #3
      I have successfully implemented a standalone Java server using the HTTPinvoker running in an embedded Jetty instance. I can post up the code if you are interested.

      Regards,
      Dave

      Comment


      • #4
        Originally posted by murrayd
        I have successfully implemented a standalone Java server using the HTTPinvoker running in an embedded Jetty instance. I can post up the code if you are interested.

        Regards,
        Dave
        Well, yes, it would be interesting.... maybe only a short document with the most important steps...

        Comment


        • #5
          I am having problems w/ConnectExceptions when testing an HttpInvoker process using embedded Jetty. I have a client Swing app and a Spring Config file, which is attempting to access and define a remote bean by way of HttpInvokerProxyFactoryBean. On the other end(The data access service), I
          have another Spring Config file which exposes the remote beans by way of HttpInvokerServiceExporter.

          I took the following approach to setting up the Jetty, web and Spring config files, separating Jetty from Spring:

          http://jroller.com/page/sjivan?entry...ty_in_a_spring

          I suspect the problem is either in the Jetty.xml or web.xml files.

          The Jetty.xml is here:
          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="Server"
                    class="org.mortbay.jetty.Server" init-method="start" destroy-method="stop">
                  <property name="connectors">
                      <list>
                          <bean id="Connector" class="org.mortbay.jetty.nio.SelectChannelConnector">
                              <property name="port" value="8080"/>
                          </bean>
                      </list>
                  </property>
          
                  <property name="handler">
                      <bean id="handlers"
                            class="org.mortbay.jetty.handler.HandlerCollection">
                          <property name="handlers">
                              <list>
                                  <bean id="contexts"
                                        class="org.mortbay.jetty.handler.ContextHandlerCollection">
                                      <property name="handlers">
                                          <list>
                                              <bean class="org.mortbay.jetty.webapp.WebAppContext">
                                                  <property name="contextPath" value="/"/>
                                                  <!--<property name="war" value="../web">-->
                                                      <property name="resourceBase" value="web">
                                                  </property>
                                              </bean>
                                          </list>
                                      </property>
                                  </bean>
                              </list>
                          </property>
                      </bean>
                  </property>
              </bean>
          </beans>
          The web.xml file is here:
          Code:
          <?xml version="1.0" encoding="ISO-8859-1"?>
          <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
          <web-app>
          
              <display-name>Backcheck Remoting</display-name>
              <description>Backcheck Remoting Services</description>
          
              <context-param>
                  <param-name>contextConfigLocation</param-name>
                  <param-value>
                      classpath:SpringConfig.xml
                  </param-value>
              </context-param>
          
              <listener>
                  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
              </listener>
          
              <servlet>
          	<servlet-name>remoting</servlet-name>
          	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          	<load-on-startup>1</load-on-startup>
              </servlet>
          
              <servlet-mapping>
          	<servlet-name>remoting</servlet-name>
          	<url-pattern>/remoting/*</url-pattern>
              </servlet-mapping>
              
          </web-app>
          The client Spring Config is here:
          Code:
          <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-2.0.xsd
                 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
                    
              <bean id="httpGroupDao" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
                <property name="serviceUrl" value="http://localhost:8080/remoting/httpGroupDao"/>
                <property name="serviceInterface" value="com.xrite.ind.backcheck.dao.group.GroupDao"/>
                <property name="httpInvokerRequestExecutor">
          	<bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"/>
                </property>
              </bean>
              
              
          </beans>
          The code to access the remote bean from the Swing Client is:
          Code:
          private static BeanFactory beanFactory;
          beanFactory = new ClassPathXmlApplicationContext("SpringClientConfig.xml");
          return (GroupDao) beanFactory.getBean("httpGroupDao");
          The Data Access Layer/Server Spring Config file is:
          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <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-2.0.xsd
                 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
          
          <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
                  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                  <property name="url" value="jdbc:mysql://localhost:3306/backcheck"/>
                  <property name="username" value="root"/>
                  <property name="password" value="goteam"/>
              </bean>
              
              <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                  <property name="dataSource" ref="dataSource"/>    
                  <property name="mappingResources">
                      <list>
                          <value>Color.hbm.xml</value>
                          <value>ReflectanceData.hbm.xml</value>
                          <value>Group.hbm.xml</value>
                          <value>Standard.hbm.xml</value>
                          <value>Sample.hbm.xml</value>
                          <value>Lab.hbm.xml</value> 
                          <value>Tag.hbm.xml</value>
                          <value>TagCategory.hbm.xml</value>
                          <value>Tolerance.hbm.xml</value>
                          <value>ViewSet.hbm.xml</value>
                          <value>ViewSetItem.hbm.xml</value>
                          <value>FilterState.hbm.xml</value>
                          <value>User.hbm.xml</value>
                          <value>FilterSort.hbm.xml</value>
                      </list>
                  </property>
                  <property name="hibernateProperties">
                      <props>
                          <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                          <prop key="hibernate.show_sql">false</prop>
                          <prop key="hibernate.hbm2ddl.auto">update</prop>
                          <prop key="current_session_context_class">thread</prop>
                          <prop key="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop>
                      </props>
                  </property>
              </bean>
              
              <bean id="transactionManager"
                    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                  <property name="sessionFactory">
                      <ref bean="sessionFactory"/>
                  </property>
              </bean> 
              
              <bean id="groupDao"
                    class="com.xrite.ind.backcheck.dao.group.GroupDAOImpl">
                  <property name="sessionFactory" ref="backcheckSessionFactory"/>
              </bean>
          
              <bean name="/httpGroupDao" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
                <property name="service" ref="groupDao"/>
                <property name="serviceInterface" value="com.xrite.ind.backcheck.dao.group.GroupDao"/>      
              </bean>
          
            </beans>

          Comment


          • #6
            Ok, I added the SimpleUrlHandlerMapping settings to my spring config on the server end, but still getting the same errors.

            Question . . . in Sanjiv Jivan's blog explaining how to embed Jetty in Spring, he mentions that using FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext(path/to/jetty.xml) to load the jetty.xml is the way to go. This, in combination w/the web.xml Spring ContextLoaderListener load applicationContext.xml, sounds like it should do the trick. However, how does the Jetty server itself get started?

            What is the most straightforward approach to tying the web.xml, jetty.xml and springapplicationcontext.xml files together?

            Comment


            • #7
              Some progress made . . . I have jetty running now based on the org.mortbay.jetty.Server bean in jetty.xml. Now getting 404s, but that may be due to a web context issue.

              Comment


              • #8
                Still getting 404 errors upon each URL request. Not sure where the problem is, but suspect either the web.xml or something missing in either the client Spring App Context config or Server Spring App Context config.

                Latest web.xml
                Code:
                <web-app>
                
                    <display-name>Backcheck Remoting</display-name>
                    <description>Backcheck Remoting Services</description>
                
                    <context-param>
                        <param-name>contextConfigLocation</param-name>
                        <param-value>
                            classpath:SpringConfig.xml
                        </param-value>
                    </context-param>
                
                    <listener>
                        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
                    </listener>
                
                    <servlet>
                	<servlet-name>remoting</servlet-name>
                	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                	<load-on-startup>1</load-on-startup>
                    </servlet>
                
                    <servlet-mapping>
                	<servlet-name>remoting</servlet-name>
                	<!--<url-pattern>/remoting/*</url-pattern>-->
                        <url-pattern>/http*</url-pattern>
                    </servlet-mapping>
                    
                </web-app>
                Latest client spring config:
                Code:
                <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-2.0.xsd
                       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">    
                            
                    <bean id="groupDao" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
                      <property name="serviceUrl" value="http://localhost:8080/httpGroupDao"/>
                      <property name="serviceInterface" value="com.xrite.ind.backcheck.dao.group.GroupDao"/>
                      <property name="httpInvokerRequestExecutor">
                	<bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"/>
                      </property>
                    </bean>
                        
                </beans>
                Latest server Spring config:
                Code:
                <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-2.0.xsd
                       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">    
                    
                    <bean id="backcheckDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
                        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                        <property name="url" value="jdbc:mysql://localhost:3306/backcheck"/>
                        <property name="username" value="root"/>
                        <property name="password" value="goteam"/>
                    </bean>
                    
                    <bean id="backcheckSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                        <property name="dataSource" ref="backcheckDataSource"/>    
                        <property name="mappingResources">
                            <list>
                                <value>Color.hbm.xml</value>
                                <value>ReflectanceData.hbm.xml</value>
                                <value>Group.hbm.xml</value>
                                <value>Standard.hbm.xml</value>
                                <value>Sample.hbm.xml</value>
                                <value>Lab.hbm.xml</value> 
                                <value>Tag.hbm.xml</value>
                                <value>TagCategory.hbm.xml</value>
                                <value>Tolerance.hbm.xml</value>
                                <value>ViewSet.hbm.xml</value>
                                <value>ViewSetItem.hbm.xml</value>
                                <value>FilterState.hbm.xml</value>
                                <value>User.hbm.xml</value>
                                <value>FilterSort.hbm.xml</value>
                            </list>
                        </property>
                        <property name="hibernateProperties">
                            <props>
                                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                                <prop key="hibernate.show_sql">false</prop>
                                <prop key="hibernate.hbm2ddl.auto">update</prop>
                                <prop key="current_session_context_class">thread</prop>
                                <prop key="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop>
                            </props>
                        </property>
                    </bean>
                    
                    <bean id="backcheckTransactionManager"
                          class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                        <property name="sessionFactory">
                            <ref bean="backcheckSessionFactory"/>
                        </property>
                    </bean> 
                    
                    <bean id="groupDao"
                          class="com.xrite.ind.backcheck.dao.group.GroupDAOImpl">
                        <property name="sessionFactory" ref="backcheckSessionFactory"/>
                    </bean>
                
                    <bean name="/httpGroupDao" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
                      <property name="service" ref="groupDao"/>
                      <property name="serviceInterface" value="com.xrite.ind.backcheck.dao.group.GroupDao"/>      
                    </bean>
                latest jetty.xml
                Code:
                <beans>
                    <bean id="Server"
                          class="org.mortbay.jetty.Server" init-method="start" destroy-method="stop">
                        <property name="connectors">
                            <list>
                                <bean id="Connector" class="org.mortbay.jetty.nio.SelectChannelConnector">
                                    <property name="port" value="8080"/>
                                </bean>
                            </list>
                        </property>
                
                        <property name="handler">
                            <bean id="handlers"
                                  class="org.mortbay.jetty.handler.HandlerCollection">
                                <property name="handlers">
                                    <list>
                                        <bean id="contexts"
                                              class="org.mortbay.jetty.handler.ContextHandlerCollection">
                                            <property name="handlers">
                                                <list>
                                                    <bean class="org.mortbay.jetty.webapp.WebAppContext">
                                                        <property name="contextPath" value="/"/>
                                                        <!--<property name="war" value="../web">-->
                                                            <property name="resourceBase" value="web">
                                                        </property>
                                                    </bean>
                                                </list>
                                            </property>
                                        </bean>
                                    </list>
                                </property>
                            </bean>
                        </property>
                    </bean>
                </beans>
                This is based on the examples in the Spring 2.0.2 Remoting/HttpInvoker section of the Docs.

                Comment


                • #9
                  Does anyone have another example of setting up a complete HttpInvoker example other than what is found in the Spring docs or Spring in action. I have followed those examples, and cannot figure out why I keep getting the 404 errors.

                  Comment


                  • #10
                    I'm guessing your problem might be to do with the serviceURL.

                    Code:
                    <property name="serviceUrl" value="http://localhost:8080/httpGroupDao"/>
                    If your exposed service is called groupDao, the servlet name is remoting and the webapp is called test......

                    Code:
                    <property name="serviceUrl" value="http://localhost:8080/test/remoting/groupDao"/>

                    Comment


                    • #11
                      OK, heres the working example I promised........ I would zip it up an attach it, but my computer isn't playing ball. The project in this example is called timeService.

                      Sooooo
                      Code:
                      tomcat
                          webapps
                              timeService
                                  applicationContext.xml
                                  invoker-servlet.xml
                                  web.xml
                      
                                  classes
                                      com/test/TimeService.class
                                      com/test/TimeServiceImpl.class
                                  lib
                                      spring.jar
                                      commons-logging-1.0.4.jar
                      The client will also require commons-codec.jar and commons-httpclient.jar on the classpath as well as the server prereqs.

                      Client

                      TimeServiceClient
                      Code:
                      package com.test;
                      
                      import org.springframework.context.ApplicationContext;
                      import org.springframework.context.support.ClassPathXmlApplicationContext;
                      
                      public class TimeServiceClient
                      {
                      	public static void main ( String [] args )
                      	{
                      		ApplicationContext context = new ClassPathXmlApplicationContext ( "client-applicationContext.xml" );
                      		TimeService timeService = ( TimeService ) context.getBean ( "timeService" );
                      		System.out.println ( timeService.getDate () );
                      		sleepPlease ();
                      		System.out.println ( timeService.getDate () );
                      	}
                      	
                      	private static void sleepPlease ()
                      	{
                      		try
                      		{
                      			Thread.sleep ( 5000 );
                      		}
                      		catch ( InterruptedException e )
                      		{
                      			// ignore
                      		}
                      	}
                      }
                      client-applicationContext.xml
                      Code:
                      <?xml version="1.0" encoding="UTF-8"?>
                      
                      <beans xmlns="http://www.springframework.org/schema/beans"
                      	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
                           
                          <bean id="httpInvokerRequestExecutor" class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"/>
                      
                          <bean id="timeService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
                      		<property name="serviceUrl" value="http://localhost:8080/timeService/invoker/timeService"/>
                      		<property name="serviceInterface" value="com.test.TimeService"/>
                              <property name="httpInvokerRequestExecutor">
                                  <ref bean="httpInvokerRequestExecutor"/>
                              </property>
                          </bean>
                          
                      </beans>
                      Server

                      TimeService
                      Code:
                      package com.test;
                      
                      import java.util.Date;
                      
                      public interface TimeService
                      {
                      	Date getDate ();
                      }
                      TimeServiceImpl
                      Code:
                      package com.test;
                      
                      import java.util.Date;
                      
                      public class TimeServiceImpl implements TimeService
                      {
                      	public Date getDate ()
                      	{
                      		return new Date ();
                      	}
                      }
                      applicationContext.xml
                      Code:
                      <?xml version="1.0" encoding="UTF-8"?>
                      
                      <beans xmlns="http://www.springframework.org/schema/beans"
                      	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
                             
                             <bean id="timeService" class="com.test.TimeServiceImpl"/>
                             
                      </beans>
                      invoker-servlet.xml
                      Code:
                      <?xml version="1.0" encoding="UTF-8"?>
                      
                      <beans xmlns="http://www.springframework.org/schema/beans"
                      	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
                             
                      	<bean name="/timeService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
                              <property name="service">
                                  <ref bean="timeService"/>
                              </property>
                              <property name="serviceInterface">
                                  <value>com.test.TimeService</value>
                              </property>
                          </bean>
                          
                      </beans>
                      web.xml
                      Code:
                      <?xml version="1.0" encoding="UTF-8"?>
                      <!DOCTYPE web-app PUBLIC
                      	"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
                      	"http://java.sun.com/dtd/web-app_2_3.dtd">
                      
                      <web-app>
                      	<display-name>Time Service</display-name>
                      	<description>Time Service</description>
                      
                      	<listener>
                      		<listener-class>
                      			org.springframework.web.context.ContextLoaderListener
                      		</listener-class>
                      	</listener>
                      
                      	<servlet>
                      		<servlet-name>invoker</servlet-name>
                      		<servlet-class>
                      			org.springframework.web.servlet.DispatcherServlet
                      		</servlet-class>
                      		<load-on-startup>1</load-on-startup>
                      	</servlet>
                      
                      	<servlet-mapping>
                      		<servlet-name>invoker</servlet-name>
                      		<url-pattern>/invoker/*</url-pattern>
                      	</servlet-mapping>
                      
                      </web-app>
                      Last edited by karldmoore; Jan 21st, 2007, 05:01 AM.

                      Comment


                      • #12
                        Originally posted by karldmoore View Post
                        I'm guessing your problem might be to do with the serviceURL.

                        Code:
                        <property name="serviceUrl" value="http://localhost:8080/httpGroupDao"/>
                        If your exposed service is called groupDao, the servlet name is remoting and the webapp is called test......

                        Code:
                        <property name="serviceUrl" value="http://localhost:8080/test/remoting/groupDao"/>

                        I think part of my problem is I am using the Netbeans IDE and I have a multi-project app. We added a new sub-project which includes all of the dao/service layer code and basically modified this, adding a web/WEB-INF directory, which contains the web.xml file(no classes or lib YET). However, seeing that this sub-project was NOT set up as a web app, a jar is being created instead of a war. So, I think the problem is two fold; project structure and directory structure.

                        At this point, I am going to replace this sub-project w/a true web app, move in the needed interfaces, classes(build to class dir) and dependencies(build to lib) and then try this again.

                        Have you ever tried to use HttpInvoker w/Jetty, however? Do I need to set the ServletContext, like I would have to do w/Tomcat?

                        Comment


                        • #13
                          I've never tried this with Jetty. The example I posted was run with Tomcat. There were no other changes required though then creating the project in webapps and putting the files in the location I stated. Hope this helps.

                          Comment


                          • #14
                            It should help. I didn't have much like getting a web-app structured sub-project to play nice w/an application parent project, so I am mimicking a web app directory and placing the files in the proper spot for the build.

                            I will let you know shortly if that works.

                            Comment


                            • #15
                              so, you did NOT create a war file like you normally would, but manually moved the classes and libs into their respective directories?

                              I am still getting 404s when using Jetty. Not sure what is going on.

                              Comment

                              Working...
                              X