6

SpringのHessian関数を介してBigDecimal値を返すリモートメソッドを呼び出すと、常にゼロが返されます。メソッドを直接呼び出すか、プレーンなヘッセサーブレット(Spring以外)を使用して正常に機能します。

これを修正するために何ができるでしょうか?

サーバー側(Tomcat 7)

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <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>

remoting-servlet.xml:

<beans>
    <context:annotation-config />
    <context:component-scan base-package="hr.spi.logic.lcspi" />

    <tx:annotation-driven proxy-target-class="true" />

    <bean name="/lcspi/lc302/poslovi" class="org.springframework.remoting.caucho.HessianServiceExporter">
        <property name="service" ref="posloviLogic" />
        <property name="serviceInterface" value="hr.spi.logic.lcspi.lc302.PosloviLogicInterface" />
    </bean>
</beans>

メソッドを呼び出すサービスクラス:

package hr.spi.logic.lcspi.lc302;

@Transactional
@Repository
public class PosloviLogic implements PosloviLogicInterface {
    @Override
    public BigDecimal test()
    {
        BigDecimal bd = new BigDecimal("2.2"); 
        return bd;      
    }
}

クライアント側

Spring構成-applicationContextHessian.xml:

<beans>
    <bean id="posloviLogic" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
        <property name="serviceUrl" value="http://localhost:8080/SpringWebTest/remoting/lcspi/lc302/poslovi" />
        <property name="serviceInterface" value="hr.spi.logic.lcspi.lc302.PosloviLogicInterface" />
    </bean>
</beans>

コンソールアプリケーションテスト:

public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContextHessian.xml");
    try {
        PosloviLogicInterface posloviLogic = (PosloviLogicInterface) context.getBean("posloviLogic");

        BigDecimal bd = posloviLogic.test();
        System.out.println(bd); // This returns 0.00

    } catch (Exception ex) {
        System.out.println(ex.getMessage());
    }
}

編集:使用されたライブラリはSpring3.2とHessian4.0.7でした

4

4 に答える 4

4

HessianServlet.setSerializerFactory()を使用して、独自のSerializerFactoryを設定し、com.caucho.hessian.io.BigDecimalDeserializerをBigDecimalのデシリアライザーとして返すことができます。

このようにパッチを適用すると、機能します。なぜこのように実装されていないのかわかりません。

http://www.jarvana.com/jarvana/view/com/caucho/hessian/4.0.7/hessian-4.0.7-src.jar!/com/caucho/hessian/server/HessianServlet.java?format=を参照してくださいわかった

于 2012-08-10T14:39:37.720 に答える
2

これは既知のバグのようです。詳細と考えられる回避策については、 http://bugs.caucho.com/view.php?id=3920を参照してください。

于 2013-01-11T09:08:45.473 に答える
2

この問題は次のように解決しました。

@keuleJと同様に、独自のSerializerFactory(以下を参照)を構築しますが、nullをチェックしないため、com.caucho.hessian.io.BigDecimalDeserializerを返しません。

public class BigDecimalSerializerFactory extends AbstractSerializerFactory {
private BigDecimalSerializer bigDecimalSerializer = new BigDecimalSerializer();
private BigDecimalDeserializer bigDecimalDeserializer = new BigDecimalDeserializer();

@Override
public Serializer getSerializer(Class cl) throws HessianProtocolException {
    if (BigDecimal.class.isAssignableFrom(cl)) {
        return bigDecimalSerializer;
    }
    return null;
}

@Override
public Deserializer getDeserializer(Class cl) throws HessianProtocolException {
    if (BigDecimal.class.isAssignableFrom(cl)) {
        return bigDecimalDeserializer;
    }
    return null;
}

}

次に、独自のデシリアライザーを定義しました。これは、値がnullでないかどうかを検証するという点で、com.couchos#sの実装とは異なります。AbstractStringValueDeserializeを拡張する必要があります!

public class BigDecimalDeserializer extends AbstractStringValueDeserializer {


@Override
public Class getType() {
    return BigDecimal.class;
}

@Override
protected Object create(String value) {
    if (null != value) {
        return new BigDecimal(value);
    } else {
        return null;
    }
}

}

シリアライザーは、BigDecimalを文字列表現にのみ転送します。

パブリッククラスBigDecimalSerializerはAbstractSerializerを拡張します{

@Override
public void writeObject(Object obj, AbstractHessianOutput out) throws IOException {

    if (obj == null)
        out.writeNull();
    else {
        Class cl = obj.getClass();

        if (out.addRef(obj))
            return;

        int ref = out.writeObjectBegin(cl.getName());

        BigDecimal bi = (BigDecimal) obj;

        if (ref < -1) {
            out.writeString("value");
            out.writeString(bi.toString());
            out.writeMapEnd();
        } else {
            if (ref == -1) {
                out.writeInt(1);
                out.writeString("value");
                out.writeObjectBegin(cl.getName());
            }

            out.writeString(bi.toString());
        }
    }
}

}

この実装は、BigDecimalだけでなく、jodaDateTimeでも機能します。

これを使用するには、SerializerFactoryをに追加する必要があります

    SerializerFactory serializerFactory = newSerializerFactory();
    serializerFactory.addFactory(new BigDecimalSerializerFactory());

これは、サーバー側とクライアント側の両方で行う必要があります。

ヒント! 私たちの場合、BigDecimalとDateTimeに複合的な問題がありました。したがって、スタックトレースとデバッグビューは奇妙でした。したがって、「非標準」オブジェクトを使用する場合は、それらのシリアル化を確認してください。

于 2012-08-17T06:03:31.353 に答える
-1

これと同じ問題が発生し、MavenCentralに配布されているヘッセ行列のjarにいくつかの主要な構成ファイルがないことがわかりました。http://hessian.caucho.com/から直接jarをダウンロードすると、jarには次のものが含まれます。

  • META-INF / hessian / serializers
  • META-INF / hessian / deserializers

これらの2つの欠落しているファイルをプロジェクトのにコピーすることで、この問題を解決しましたsrc/main/resources

ボーナス:このソリューションは、ヘシアンシリアル化で発生した問題も修正しましたjava.util.Locale

于 2017-01-25T20:30:43.037 に答える