sapjco3.jarドライバを使用してSAPに正常に接続するSpring MVC(Spring framework 4.1.1)Java 1.8アプリケーションを作成しました。これをCustomDestinationDataProviderテクニックを使用して実行しました。私はこのドライブを使用して、SAP R/3システムのRFCを呼び出します。 Javaコードは、AngularJSフロントエンドアプリケーションからのAPI呼び出しによって実行されます。ここでsapjco3ドライバの問題
NestedServletException: Handler processing failed; nested exception is
java.lang.Error: java.lang.IllegalStateException: DestinationDataProvider
already registered
私CustomDestinationDataProvider.javaファイルの内容です:
public class CustomDestinationDataProvider {
public class MyDestinationDataProvider implements DestinationDataProvider {
private DestinationDataEventListener eL;
private HashMap<String, Properties> secureDBStorage = new HashMap<String, Properties>();
public Properties getDestinationProperties(String destinationName) {
try {
Properties p = secureDBStorage.get(destinationName);
if(p!=null) {
if(p.isEmpty())
throw new DataProviderException(DataProviderException.Reason.INVALID_CONFIGURATION, "destination configuration is incorrect", null);
return p;
}
return null;
} catch(RuntimeException re) {
throw new DataProviderException(DataProviderException.Reason.INTERNAL_ERROR, re);
}
}
public void setDestinationDataEventListener(DestinationDataEventListener eventListener) {
this.eL = eventListener;
}
public boolean supportsEvents() {
return true;
}
public void changeProperties(String destName, Properties properties) {
synchronized(secureDBStorage) {
if(properties==null) {
if(secureDBStorage.remove(destName)!=null)
eL.deleted(destName);
} else {
secureDBStorage.put(destName, properties);
eL.updated(destName); // create or updated
}
}
}
}
public ArrayList<MaterialBean> executeAvailabilityCall(Properties connectProperties, String searchString) {
String destName = "ABAP_AS";
SAPDAO sapDAO = new SAPDAO();
ArrayList<MaterialBean> searchResults = new ArrayList<MaterialBean>();
MyDestinationDataProvider myProvider = new MyDestinationDataProvider();
JCoDestination dest;
try {
com.sap.conn.jco.ext.Environment.registerDestinationDataProvider(myProvider);
} catch(IllegalStateException providerAlreadyRegisteredException) {
}
myProvider.changeProperties(destName, connectProperties);
try {
dest = JCoDestinationManager.getDestination(destName);
searchResults = sapDAO.searchAvailability(dest, searchString);
} catch(JCoException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
myProvider.changeProperties(destName, null);
try {
com.sap.conn.jco.ext.Environment.unregisterDestinationDataProvider(myProvider);
} catch(IllegalStateException providerAlreadyRegisteredException) {
throw new Error(providerAlreadyRegisteredException);
}
return searchResults;
} // end method executeAvailabilityCall()
} // end class CustomDestinationProvider()
を私はSAPへの呼び出しが発生した時間の約5%をoccuring発見した
何かが次のエラーが発生しています
複数のAPIコールが同時に発生していて、最初のクエリで宛先データプロバイダが登録されると、宛先データプロバイダを登録しようとする後続のクエリも同じ値を使用しているため失敗しますために ' executeAvailabilityCallメソッドの「destName」。
最初のグレースでは、すべてのクエリに「ABAP_AS」を使用するのではなく、destName変数に動的値を使用する必要があるようです。このような何かに
String destName = "ABAP_AS";
::他の言葉で、私は次の行を変更する必要があり
String destName = "ABAP_AS_" + LocalDateTime.now();
これは、このようにユニーク先プロバイダ名をdestName変数に一意の値を保証します。
これを試すことの知恵について考えてみましょうか?これが良い考えではない場合は、他にどのような解決策を検討する価値がありますか?
'MyDestinationDataProvider'を一度登録することについては、シングルトンスタイルのクラスで行うべきか、データプロバイダがまだ登録されていない場合にのみ実行される 'registerDestinationDataProvider'ラインの周りに条件付きロジックを使用する必要がありますか? – Stephen
「DestinationDataProvider」の登録は、一度しか呼び出されない初期化ルーチン内で行うことをお勧めします。'DestinationDataProvider'がすでに登録されているかどうかを繰り返しチェックすることは、私の意見では効率的なコーディングスタイルではありません。 – Trixx
それは良いアイデアのように思えます。あなたのご意見をありがとうございました! :) – Stephen