Mantis Bugtracker
  

Viewing Issue Simple Details Jump to Notes ] View Advanced ] Issue History ] Print ]
ID Category Severity Reproducibility Date Submitted Last Update
0000103 [Resin] minor always 04-14-05 00:00 05-11-05 00:00
Reporter user125 View Status public  
Assigned To
Priority normal Resolution fixed  
Status closed   Product Version 3.0.12
Summary 0000103: JMS with JDBC on PostgreSQL
Description RSN-94
I am trying to send a message in a queue and I get this exception:

11:30:25,790 admin ERROR org.springframework.web.servlet.DispatcherServlet:404 - Could not complete request
org.springframework.jms.UncategorizedJmsException: Uncategorized exception occured during JMS processing; nested exception is com.caucho.jms.JMSExceptionWrapper: null; nested exception is com.caucho.jms.JMSExceptionWrapper: null
com.caucho.jms.JMSExceptionWrapper
        at com.caucho.jms.jdbc.JdbcQueue.send(JdbcQueue.java:163)
        at com.caucho.jms.session.SessionImpl.send(SessionImpl.java:752)
        at com.caucho.jms.session.MessageProducerImpl.send(MessageProducerImpl.java:161)
        at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:776)
        at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:762)
        at org.springframework.jms.core.JmsTemplate$2.doInJms(JmsTemplate.java:739)
        at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:706)
        at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:718)
        at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:737)
        at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:788)
        at com.nobelglobe.common.model.security.service.impl.SecurityServiceImpl.sendUserSyncMessage(SecurityServiceImpl.java:176)
        at com.nobelglobe.common.model.security.service.impl.SecurityServiceImpl.createUser(SecurityServiceImpl.java:145)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:324)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:155)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:122)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:57)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174)
        at $Proxy14.createUser(Unknown Source)
        at com.nobelglobe.common.controller.controllers.security.UserController.onSubmit(UserController.java:53)
        at org.springframework.web.servlet.mvc.SimpleFormController.processFormSubmission(SimpleFormController.java:248)
        at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:243)
        at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:128)
        at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:44)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:675)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:623)
        at org.springframework.web.servlet.FrameworkServlet.serviceWrapper(FrameworkServlet.java:384)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:353)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:152)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:90)
        at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:99)
        at com.nobelglobe.common.controller.filters.logging.LogMdcFilter.doFilterInternal(LogMdcFilter.java:27)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
        at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
        at com.nobelglobe.common.controller.filters.security.SecurityFilter.doFilterInternal(SecurityFilter.java:119)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
        at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
        at com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:118)
        at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52)
        at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
        at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:172)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
        at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
        at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:163)
        at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:208)
        at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:259)
        at com.caucho.server.port.TcpConnection.run(TcpConnection.java:341)
        at com.caucho.util.ThreadPool.runTasks(ThreadPool.java:467)
        at com.caucho.util.ThreadPool.run(ThreadPool.java:408)
        at java.lang.Thread.run(Thread.java:534)
Caused by: java.lang.NegativeArraySizeException
        at org.postgresql.jdbc2.PreparedStatement.setBinaryStream(PreparedStatement.java:582)
        at com.caucho.sql.UserPreparedStatement.setBinaryStream(UserPreparedStatement.java:343)
        at com.caucho.sql.UserPreparedStatement.setBinaryStream(UserPreparedStatement.java:343)
        at com.caucho.jms.jdbc.JdbcMessage.send(JdbcMessage.java:289)
        at com.caucho.jms.jdbc.JdbcQueue.send(JdbcQueue.java:161)
        ... 53 more

 
I use springframework 1.2.RC 1.
My code looks like this:
 private void sendUserSyncMessage(final User user, final int type) {
        jmsTemplate.convertAndSend(jmsQueue, user);
        jmsTemplate.send(jmsQueue, new MessageCreator() {
                    public Message createMessage(Session session) throws JMSException {
                        Message message = session.createObjectMessage(user);
                        return message;
                    }
                });
    }


My JMS related configurations on Resin are:

    <database>
        <jndi-name>jdbc/nobelservices</jndi-name>
        <driver type="org.postgresql.Driver">
            <url>jdbc:postgresql://localhost:5432/nobelservices</url> [^]
            <user>nobelservices</user>
            <password>nobelservices</password>
        </driver>
        <prepared-statement-cache-size>8</prepared-statement-cache-size>
        <max-connections>200</max-connections>
        <max-idle-time>30s</max-idle-time>
    </database>


    <resource jndi-name="jms/factory" type="com.caucho.jms.ConnectionFactoryImpl">
        <init>
            <data-source>jdbc/nobelservices</data-source>
        </init>
    </resource>
    <resource jndi-name="jms/security-queue" type="com.caucho.jms.jdbc.JdbcQueue">
        <init>
            <queue-name>security-queue</queue-name>
            <data-source>jdbc/nobelservices</data-source>
        </init>
    </resource>

If I have time, will try this on a newer postgres with a newer driver to see if it's a PostgreSQL related issue.
Additional Information Red Hat Linux 8, Resin 3.0.12, Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_07-b05), PostgreSQL 7.2.1, JDBC driver: pg72jdbc2.jar
Attached Files

- Relationships

- Notes
(0000117)
user125
04-14-05 00:00

I have downloaded the resin code and started looking into it.
First of all it seems the exception I reported is originated from a wrong piece of code. Let me explain:
The com.caucho.jms.jdbc.JdbcMessage.send() method does something like this:

 public long send(Message message, int queue, long expireTime)
    throws SQLException, IOException, JMSException
  {
  ........
   if (_messageSequence != null) {//which should be the case for PostgreSQL
        .....
        pstmt.setBinaryStream(i++, header.openRead(), header.getLength());
    
        ......
   } else {//for databases that support auto-increment columns
        ...........
        pstmt.setBinaryStream(i++, header.openRead(), header.getLength());//this is where my exception comes from
        .......
   }
   
   
So, the first thing that I found interesting is that the flow goes on the wrong case (the else branch). The second thing is why header.getLength() returns a negative integer in this case. I suspect that it would throw the same kind of exception if it would go on the if branch.

For the first thing I think I have actually found the cause: the _messageSequence is initialized in the init method, which does something like this:

public void init() throws ConfigException, SQLException {
    ...............
    Statement stmt = conn.createStatement();
    String sql = "SELECT 1 FROM " + _messageTable + " WHERE 1=0";

    try {
        ResultSet rs = stmt.executeQuery(sql);
        rs.next();
        rs.close();
        stmt.close();
    
        return;//the method will return here after the resin_jms_message is created in the database.
    } catch (SQLException e) {
    log.finest(e.toString());
    }
    ..............
    JdbcMetaData metaData = _jdbcManager.getMetaData();
    String identity = "";
    if (metaData.supportsIdentity()){
        identity = " auto_increment";
    }else{
        _messageSequence = _messageTable + "_cseq";
    }
    .........
}

First time when I started Resin, it created the 'resin_jms_message' table in the database. After I restarted Resin,
the table is already in the database and the 'SELECT 1 FROM resin_jms_message WHERE 1=0' actually executes with
success. So, the init method simply returns, and the _messageSequence does get to be initialized properly.

I will investigate more for the second issue, the java.lang.NegativeArraySizeException.

I would appreciate some feedback and maybe some hints.

Mircea
 
(0000118)
user125
04-14-05 00:00

Hi, I have changed the JdbcMessage class as I said in comment 2, and everythinmg seems to work. Here is the modified init() method:
public void init()
    throws ConfigException, SQLException
  {
    _messageTable = _jdbcManager.getMessageTable();
    _dataSource = _jdbcManager.getDataSource();
JdbcMetaData metaData = _jdbcManager.getMetaData();
      
      String identity = "";

      if (metaData.supportsIdentity())
    identity = " auto_increment";
      else
    _messageSequence = _messageTable + "_cseq";
      
    Connection conn = _dataSource.getConnection();
    try {
      Statement stmt = conn.createStatement();
      String sql = "SELECT 1 FROM " + _messageTable + " WHERE 1=0";

      try {
    ResultSet rs = stmt.executeQuery(sql);
    rs.next();
    rs.close();
    stmt.close();

    return;
      } catch (SQLException e) {
    log.finest(e.toString());
      }

      String blob = _jdbcManager.getBlob();
      String longType = _jdbcManager.getLongType();
                               
      log.info(L.l("creating JMS message table {0}", _messageTable));

      
      
      sql = ("CREATE TABLE " + _messageTable + " (" +
         " m_id " + longType + " PRIMARY KEY" + identity + "," +
         " queue INTEGER NOT NULL," +
         " connection VARCHAR(255)," +
         " consumer " + longType + "," +
         " delivered INTEGER NOT NULL," +
         " msg_type INTEGER NOT NULL," +
         " expire " + longType + " NOT NULL," +
         " header " + blob + "," +
         " body " + blob +
         ")");

      stmt.executeUpdate(sql);

      if (_messageSequence != null) {
    stmt.executeUpdate(metaData.createSequenceSQL(_messageSequence, 1));
      }
    } finally {
      conn.close();
    }
  }


I plan to use this JMS + JDBC feature on PostgreSQL a project I am working on right now. It is just a small change and I hope it can be included in the next Resin release. I am just curious what is the date of the next relesease, because we have a tight deadline on the project, and lots of things are dependent on this feature.
 
(0000119)
ferg
04-14-05 00:00

ejb/6790

thanks for all the work looking into this.
 

- Issue History
Date Modified Username Field Change
04-14-05 00:00 user125 New Issue
11-30-05 00:00 administrator Fixed in Version  => 3.0.13


Mantis 1.0.0rc3[^]
Copyright © 2000 - 2005 Mantis Group
39 total queries executed.
29 unique queries executed.
Powered by Mantis Bugtracker