Mantis Bugtracker
  

Viewing Issue Advanced Details Jump to Notes ] View Simple ] 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 Platform
Status closed   OS
Projection none   OS Version
ETA none Fixed in Version 3.0.13 Product Version 3.0.12
  Product Build 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.
Steps To Reproduce
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