Java 在EJB3中使用StringBuffer或StringBuilder

Java 在EJB3中使用StringBuffer或StringBuilder,java,ejb,stringbuilder,stringbuffer,Java,Ejb,Stringbuilder,Stringbuffer,在EJB3应用程序(在WebSphereApplicationServerV7.0.0.21上)中,我有一个返回字符串的方法。在方法中,我使用StringBuffer生成动态字符串(也使用StringBuilder进行了尝试,结果相同)。偶尔出现的问题是字符串的内容都被打乱了。我为这个问题挣扎了很长一段时间 编辑: 添加了dao.properties、spring.xml、dao.java、DaoBeanLocal.java、DaoBean.java和DaoSpringJdbc.java的代码

在EJB3应用程序(在WebSphereApplicationServerV7.0.0.21上)中,我有一个返回字符串的方法。在方法中,我使用StringBuffer生成动态字符串(也使用StringBuilder进行了尝试,结果相同)。偶尔出现的问题是字符串的内容都被打乱了。我为这个问题挣扎了很长一段时间

编辑

  • 添加了dao.properties、spring.xml、dao.java、DaoBeanLocal.java、DaoBean.java和DaoSpringJdbc.java的代码
  • 我正在使用JavaEE5、JRE1.6和SpringJDBC3.0.6
示例1

用户A和B在不同的时间调用生成文档的方法,并且都得到了正确的结果

用户A的结果:

字符串1:1

弦2:2

3:3

弦4:4

和用户B的结果:

第1:5节

第2章第6节

第3章第7节

第4章第8节

示例2

用户A和B同时调用生成文档的方法,两者得到相同的置乱结果(部分响应来自用户A,部分响应来自用户B):

字符串1:1

弦2:2

第3章第7节

第4章第8节

示例代码

dao.properties

# jndi lookup string

jndi.datasource = jdbc/DS

# integers
select.integers = \
    SELECT \
        num1 \
    FROM \
        DBINTEGERS \
    WHERE \
        param1 = :param1 \
        AND param2 = :param2 \
    ORDER BY num1 \
    WITH UR

# custom object
select.custom.object = \
    SELECT \
        number1, number2, number3, number4 \
    FROM \
        DB_OBJECTS \
    WHERE \
        param1 = :param1 \
    ORDER BY number1 \
    WITH UR
spring.xml

<?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:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">

    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:dao.properties</value>
            </list>
        </property>
        <property name="order" value="1" />
        <property name="ignoreUnresolvablePlaceholders" value="false" />
        <property name="localOverride" value="true" />
    </bean>

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.WebSphereDataSourceAdapter">
        <property name="targetDataSource">
            <bean class="org.springframework.jndi.JndiObjectFactoryBean">
                <property name="jndiName" value="${jndi.datasource}" />
                <property name="resourceRef" value="true" />
            </bean>
        </property>
    </bean>

    <bean id="abstractDao" abstract="true">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="dao" class="org.example.beans.dao.DaoSpringJdbc" parent="abstractDao">
        <property name="selectIntegers" value="${select.integers}" />
        <property name="selectCustomObject" value="${select.custom.object}" />
    </bean>
</beans>
DaoBean.java

package org.example.beans.dao;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJBException;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

@Stateless
public class DaoBean implements DaoBeanLocal {
    private Dao dao;

    @PostConstruct
    protected void init() {

        try {
            this.dao = (Dao) getBeanFactory().getBean("dao", Dao.class);
        } catch (Exception e) {
        //  log.error(e.getMessage(), e);

            throw new EJBException(e.getMessage(), e);
        }
    }

    @PreDestroy
    protected void destroy() {
        if (this.dao != null) {
            this.dao = null;
        }
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public List<Integer> selectINTEGERS(String param1, String param2) throws SQLException {
        return dao.selectINTEGERS(param1, param2);
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public List<CustomObject> selectCustomObject(Integer param1) throws SQLException {
        return dao.selectCustomObject(param1);
    }
}
CustomException.java

package org.example.beans.exceptions;

import javax.ejb.ApplicationException;

@ApplicationException(rollback = true)
public class CustomException extends Exception {
    private static final long serialVersionUID = 1L;

    public CustomException() {
        super();
    }

    public CustomException(Throwable t) {
        super(t);
    }

    public CustomException(String detailMessage) {
        super(detailMessage);
    }

    public CustomException(String detailMessage, Throwable t) {
        super(detailMessage, t);
    }
}
Data.java

package org.example.beans.data;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.example.beans.models.CustomObject;
import org.example.beans.dao.DaoBeanLocal;
import org.example.beans.exceptions.CustomException;

public class Data {
    public void getContent(StringBuffer doc, DaoBeanLocal dao, Integer param1) throws CustomException {
        List<CustomObject> list = dao.selectCustomObject(param1);
        for (CustomObject obj : list) {
            doc.append("------------------");
            doc.append("String1: ").append(obj.getNumber1()).append("\n");
            doc.append("String2: ").append(obj.getNumber2()).append("\n");
            doc.append("String3: ").append(obj.getNumber3()).append("\n");
            doc.append("String4: ").append(obj.getNumber4()).append("\n");
        }
    }
}
package org.example.beans.data;
导入java.util.array;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
导入org.example.beans.models.CustomObject;
导入org.example.beans.dao.DaoBeanLocal;
导入org.example.beans.exceptions.CustomException;
公共类数据{
public void getContent(StringBuffer doc、daobeannlocal dao、Integer param1)引发CustomException{
List List=dao,选择CustomObject(参数1);
用于(CustomObject对象:列表){
追加文件(“--------------------------”;
doc.append(“String1:”).append(obj.getNumber1()).append(“\n”);
doc.append(“String2:”).append(obj.getNumber2()).append(“\n”);
doc.append(“String3:”).append(obj.getNumber3()).append(“\n”);
doc.append(“String4:”).append(obj.getNumber4()).append(“\n”);
}
}
}
DocumentBean.java

package org.example.beans;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

import org.example.beans.exceptions.CustomException;
import org.example.beans.data.Data;
import org.example.beans.dao.DaoBeanLocal;

@Stateless
public class DocumentBean implements DocumentRemote {
    @PostConstruct
    protected void init() {
    }

    @PreDestroy
    protected void destroy() {
    }

    // DAO local ejb
    @EJB
    private DaoBeanLocal dao;

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public String generateDocument(String param1, String param2) throws CustomException {
        StringBuffer doc = new StringBuffer(10000);

        try {
            // some utility class
            Data data1 = new Data();
            Data data2 = new Data();
            Data data3 = new Data();
            Data data4 = new Data();

            // some data from database
            List<Integer> list = dao.selectIntegers(param1, param2);

            for (Integer param1 : list) {
                // a lot of usage of StringBuffer inside methods
                data1.getContent(doc, dao, param1);
                data2.getContent(doc, dao, param1);
                data3.getContent(doc, dao, param1);
                data4.getContent(doc, dao, param1);
            }
        } catch (CustomException e) {
            log.error(e.getMessage(), e);

            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);

            throw new CustomException(e.getMessage(), e);
        }

        String result = doc.toString();

        return result;
    }
}
package org.example.beans;
导入java.util.List;
导入javax.annotation.PostConstruct;
导入javax.annotation.PreDestroy;
导入javax.ejb.ejb;
导入javax.ejb.EJBException;
导入javax.ejb.Stateless;
导入javax.ejb.TransactionAttribute;
导入javax.ejb.TransactionAttributeType;
导入org.example.beans.exceptions.CustomException;
导入org.example.beans.data.data;
导入org.example.beans.dao.DaoBeanLocal;
@无国籍
公共类DocumentBean实现DocumentRemote{
@施工后
受保护的void init(){
}
@发情前期
受保护的无效销毁(){
}
//DAO本地ejb
@EJB
私人道具本地道具;
@凌驾
@TransactionAttribute(TransactionAttributeType.REQUIRES\u NEW)
公共字符串generateDocument(字符串参数1,字符串参数2)引发CustomException{
StringBuffer文档=新StringBuffer(10000);
试一试{
//一些实用程序类
Data data1=新数据();
Data data2=新数据();
Data data3=新数据();
Data data4=新数据();
//数据库中的一些数据
List List=dao.selectIntegers(参数1,参数2);
for(整数参数1:列表){
//StringBuffer在方法内部的大量使用
data1.getContent(doc、dao、param1);
data2.getContent(doc、dao、param1);
data3.getContent(doc、dao、param1);
data4.getContent(doc、dao、param1);
}
}捕获(自定义异常){
log.error(e.getMessage(),e);
投掷e;
}捕获(例外e){
log.error(e.getMessage(),e);
抛出新的CustomException(e.getMessage(),e);
}
字符串结果=doc.toString();
返回结果;
}
}
我想这就是同步线程的问题所在。我认为EJB上下文处理同步,每个远程调用在单独的线程中进行


有人知道如何解决这个问题吗?

正如您所说,每个EJB都是独立的线程,因此StringBuffer不会以任何方式共享。将dao添加到列表中,可能存在问题。@谢谢您的输入。没想到dao可能是问题的根源。我已经更新了我的问题…您确定输出不是这样的吗:例如:String1:5 String2:6 String1:1 String2:2 String3:7 String4:8 String3:3 String4:4?这是完全合法的,因为写入日志是不同步的。@Gas GUI应用程序(Java AWT)使用EJB客户端,返回的字符串显示在文本区域中。写入日志不是问题,也没有使用。你觉得DAO代码怎么样?为什么您认为DAO可能会导致问题?@Gas输出看起来有一点来自用户a响应,而有一点来自用户B响应-似乎有两个不同的线程混合在一起。我不能重复这个错误。
package org.example.beans.models;

public class CustomObject {
    private int number1;
    private int number2;
    private int number3;
    private int number4;

    public int getNumber1() {
        return this.number1;
    }

    public void setNumber1(int number1) {
        this.number1 = number1;
    }

    public int getNumber1() {
        return this.number1;
    }

    public void setNumber2(int number2) {
        this.number2 = number2;
    }

    public int getNumber2() {
        return this.number2;
    }

    public void setNumber3(int number3) {
        this.number3 = number3;
    }

    public int getNumber3() {
        return this.number3;
    }

    public void setNumber4(int number4) {
        this.number4 = number4;
    }

    public int getNumber4() {
        return this.number4;
    }
}
package org.example.beans.exceptions;

import javax.ejb.ApplicationException;

@ApplicationException(rollback = true)
public class CustomException extends Exception {
    private static final long serialVersionUID = 1L;

    public CustomException() {
        super();
    }

    public CustomException(Throwable t) {
        super(t);
    }

    public CustomException(String detailMessage) {
        super(detailMessage);
    }

    public CustomException(String detailMessage, Throwable t) {
        super(detailMessage, t);
    }
}
package org.example.beans.data;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.example.beans.models.CustomObject;
import org.example.beans.dao.DaoBeanLocal;
import org.example.beans.exceptions.CustomException;

public class Data {
    public void getContent(StringBuffer doc, DaoBeanLocal dao, Integer param1) throws CustomException {
        List<CustomObject> list = dao.selectCustomObject(param1);
        for (CustomObject obj : list) {
            doc.append("------------------");
            doc.append("String1: ").append(obj.getNumber1()).append("\n");
            doc.append("String2: ").append(obj.getNumber2()).append("\n");
            doc.append("String3: ").append(obj.getNumber3()).append("\n");
            doc.append("String4: ").append(obj.getNumber4()).append("\n");
        }
    }
}
package org.example.beans;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

import org.example.beans.exceptions.CustomException;
import org.example.beans.data.Data;
import org.example.beans.dao.DaoBeanLocal;

@Stateless
public class DocumentBean implements DocumentRemote {
    @PostConstruct
    protected void init() {
    }

    @PreDestroy
    protected void destroy() {
    }

    // DAO local ejb
    @EJB
    private DaoBeanLocal dao;

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public String generateDocument(String param1, String param2) throws CustomException {
        StringBuffer doc = new StringBuffer(10000);

        try {
            // some utility class
            Data data1 = new Data();
            Data data2 = new Data();
            Data data3 = new Data();
            Data data4 = new Data();

            // some data from database
            List<Integer> list = dao.selectIntegers(param1, param2);

            for (Integer param1 : list) {
                // a lot of usage of StringBuffer inside methods
                data1.getContent(doc, dao, param1);
                data2.getContent(doc, dao, param1);
                data3.getContent(doc, dao, param1);
                data4.getContent(doc, dao, param1);
            }
        } catch (CustomException e) {
            log.error(e.getMessage(), e);

            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);

            throw new CustomException(e.getMessage(), e);
        }

        String result = doc.toString();

        return result;
    }
}