1

アプリケーションは、Mule以外のスレッド、つまりアプリケーションによって作成されたスレッドのコンポーネントバインディングを介して作成されたプロキシを呼び出すことができますか?これを実行しようとすると、org.mule.DefaultMuleEvent:268でNullPointerExceptionが発生します。

それはMuleEE3.3.0にあります

ありがとう。

アップデート:

ミュールコード

<mule ...>
    <vm:endpoint path="entryPoint" name="entryPoint" />

    <flow name="entryPoint.Flow">
        <inbound-endpoint ref="entryPoint" exchange-pattern="request-response" />
        <component class="foo.Component">
            <binding interface="foo.Interface" method="echo">
            <vm:outbound-endpoint path="foo.Interface.echo" exchange-pattern="request-response" />
        </binding>
        </component>
    </flow>

    <flow name="foo.Interface.echo">
        <vm:inbound-endpoint path="foo.Interface.echo" exchange-pattern="request-response" />
        <logger level="INFO" />
    </flow>

</mule>

Javaコンポーネント

package foo;

import static java.util.concurrent.Executors.newSingleThreadExecutor;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class Component {

    private Interface i;

    public String foo(final String input) {
        return callInterfaceOnAWorkerThreadWith(input);
    }

    public void setInterface(final Interface i) {
        this.i = i;
    }

    private String callInterfaceOnAWorkerThreadWith(final String input) {
        ExecutorService executorService = newSingleThreadExecutor();
        Future<String> future = executorService.submit(new Callable<String>() {

            @Override
            public String call() throws Exception {
                return i.echo(input);
            }

        });
        executorService.shutdown();
        try {
            executorService.awaitTermination(60, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        try {
            return future.get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }

    }

}

Javaインターフェース

package foo;

public interface Interface {

    String echo(String input);

}

ラバアプリを実行するためのテストフィクスチャ

package foo;

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.mule.api.MuleException;
import org.mule.api.MuleMessage;
import org.mule.api.client.MuleClient;
import org.mule.tck.junit4.FunctionalTestCase;

@RunWith(MockitoJUnitRunner.class)
public class ATest extends FunctionalTestCase {

    @Test
    public void echo() {
        final MuleClient client = muleContext.getClient();
        MuleMessage reply = send(client, "entryPoint", "a string");
        assertEquals("a string", reply.getPayload());
    }

    @Override
    protected String getConfigResources() {
        return "app/componentbindingonanotherthread.xml";
    }

    private MuleMessage send(final MuleClient client, final String url, final Object payload) {
        try {
            return client.send(url, payload, null, RECEIVE_TIMEOUT);
        } catch (final MuleException e) {
            throw new RuntimeException(e);
        }
    }

}

上記のコードを実行すると、ログに次の例外が表示されます。

Root Exception stack trace:
java.lang.NullPointerException
    at org.mule.DefaultMuleEvent.<init>(DefaultMuleEvent.java:268)
    at org.mule.component.BindingInvocationHandler.invoke(BindingInvocationHandler.java:96)
    at $Proxy14.echo(Unknown Source)
4

1 に答える 1

1

問題は、Muleが を使用BindingInvocationHandlerして電流をルックアップするという事実に要約されます。これはバインドされています。つまり、別のスレッドでバインドを実行しているため、Mule コンテキストが失われ、上記のエラーが発生します。MuleEventRequestContext.getEvent()ThreadLocal

Mule のワーカー マネージャー (MuleContext から取得できます) を使用すると、独自の を使用するより優れた設計になりますが、(非推奨の!)コンストラクトExecutorServiceに依存しているため、問題は解決しません。BindingInvocationHandlerRequestContext.getEvent()

実際に調べてみると、あまり意味がないので、デザインを再考する必要があると思います。別のスレッドでバインディングを実行しても、リクエストとレスポンスであるため何も得られないentryPointため、インバウンドスレッドがプールから動員されます。このスレッドは、バインディング自体がこのスレッドによって実行されるか別のスレッドによって実行されるかに関係なく、バインディングが完了するまでブロックされたままになります。

私を逃れる理由で、別のスレッドでバインディングを実行する必要がある場合は、バインディングを別のフローに移動し、request-replyメッセージプロセッサで呼び出します。

ここでの教訓は次のとおりです。Mule にはすでに豊富なスレッド モデルがあり、独自のコーディングを行うよりも、Mule が提供するスレッド構造 ( 、request-replyVMキュー) を使用してそのモデル内で遊ぶ方がよいでしょう。asyncone-way

于 2012-11-23T17:47:43.893 に答える