we're currently setting up a SAP-IDoc JCo-Server.
There are two interfaces for transaction management und receiving IDOCs.
Transaction management (JCoServerTIDHandler):
boolean checkTID(com.sap.conn.jco.server.JCoServerContext arg0, java.lang.String arg1);
void confirmTID(com.sap.conn.jco.server.JCoServerContext arg0, java.lang.String arg1);
void commit(com.sap.conn.jco.server.JCoServerContext arg0, java.lang.String arg1);
void rollback(com.sap.conn.jco.server.JCoServerContext arg0, java.lang.String arg1);
IDOC-Handling (JCoIDocHandler):
void handleRequest(com.sap.conn.jco.server.JCoServerContext arg0, com.sap.conn.idoc.IDocDocumentList arg1);
There's only checkTID with a return value. No method has a throws declaration.
How to tell the calling SAP-System that e.g. commit/confirmTID or handleRequest failed ?
Throw a runtime exception ? What happens afterwards, does SAP resend the IDOCs or restart the transaction ?
Is there any documentation how to handle these error situations ?
Any help is welcome, if my description is unclear or incomplete, please don't hesitate to ask.
Thanks a lot.
Related
I want to keep track of records which was failed during the reading step of a job. I have used SkipListener for this.
public class SkipListener implements org.springframework.batch.core.SkipListener {
public void onSkipInProcess(Object arg0, Throwable arg1) {
}
public void onSkipInRead(Throwable arg0) {
System.out.println(arg0);
}
public void onSkipInWrite(Object arg0, Throwable arg1) {
}
}
I want to store the line skipped by reader in another csv file.
From the above onSkipInRead(Throwable arg0) method i am getting throwable object like this :
org.springframework.batch.item.file.FlatFileParseException: Parsing error at line: 5 in resource=[class path resource [files/input2.csv]], input=[1005,anee,Active,500000,34,888]
I want only record as : 1005,anee,Active,500000,34,888
How can I get this or I have to parse manually the throwable object and get this?
Second Question is that : I want to keep track of Number of items actually submitted to job, Number of item skipped, Number of item processed successfully, Is there any support provided by Spring Batch for this?
For your first question, you have to parse manually the exception message, since the item couldn't be read.
For your second question, SpringBatch provides methods on the StepExecution objects :
Read : stepExecution.getReadCount()
Read Failed : stepExecution.getReadSkipCount()
Processed : stepExecution.getProcessCount()
Processed Failed : stepExecution.getProcessSkipCount()
Written : stepExecution.getWriteCount()
Written Failed : stepExecution.getWriteSkipCount()
I want to test the automatically rolling back of an transaction. Therefore, I implemented a simple bean[src] that throws an system exception which should result in an automatically roll back[1]. I also implemented the interface SessionSynchronization so I can affect the rollback with the method afterCompletion. But the argument of this method is true which I expect to be false in regards to the specs[2].
Am I missing something or is this a bug in JBoss 7? I already searched the bug tracker but did not find anything ... maybe I used the wrong words?
If this is not a bug: are there any settings regarding to set the afterCompletion parameter to false if a system or an application exception occures?
[1]: "There are two ways to roll back a container-managed transaction. First, if a system exception is thrown, the container will automatically roll back the transaction. Second, by invoking the setRollbackOnly method of the EJBContext interface, the bean method instructs the container to roll back the transaction. If the bean throws an application exception, the rollback is not automatic but can be initiated by a call to setRollbackOnly." http://docs.oracle.com/javaee/6/tutorial/doc/bncij.html
[2]: "The afterCompletion method notifies a stateful session bean instance that a transaction commit protocol has completed, and tells the instance whether the transaction has been committed or rolled back." http://docs.oracle.com/javaee/6/api/javax/ejb/SessionSynchronization.html
[src]:
#Stateful
#LocalBean
public class RollbackTestBean implements RollbackTest, SessionSynchronization {
int counter = 0;
int counterBuffer = 0;
private final Logger logger = Logger.getLogger(this.getClass().getName());
#Override
public int getCounter() {
return counter;
}
#Override
public void throwSystemException() throws SystemException {
counter++;
throw new SystemException();
}
#Override
public void afterBegin() throws EJBException, RemoteException {
logger.info("[TX]: after begin");
counterBuffer = counter;
}
#Override
public void afterCompletion(boolean success) throws EJBException, RemoteException {
logger.info("[TX]: after completion: " + success);
if (!success)
counter = counterBuffer;
}
#Override
public void beforeCompletion() throws EJBException, RemoteException {
logger.info("[TX]: before completion");
}
}
There are two SystemExceptions
org.omg.CORBA.SystemException subclass of RuntimeException
javax.transaction.SystemException subclass of Exception
I hope you are using org.omg.CORBA.SystemException
EJB3.1 spec says, if its RuntimeException or ApplicationException, the transaction needs to be rolled back.
As far as I can see, ApplcationException is handled correctly in JBoss 7.1.1, but not RuntimeException.
With RuntimeException, there is a similar issue reported when remove() is called on Statefull bean, reference here. I am getting the same error message when I try to throw RuntimeException. Its fixed in Verion 7.1.3 I think. But I have not tested myself.
You can try 7.1.3, if you are looking for a fix. If you have your Exception and wants transaction rollback, use
#ApplicationException(rollback=true)
Maddy
I'm just trying to stub the method but getting null pointer exception. I'm kinda blank what's going on here.
my method :
OauthStatus validate(HttpServletRequest request,
boolean accessTokenRequired) throws OauthProviderException;
and Stub is :
Mockito.when(oauthProviderMock.validate((MockHttpServletRequest) Mockito.anyObject(), (boolean)Mockito.anyBoolean())).
thenReturn(new OauthStatus());
i see there is no wrong in mocking but throws nullpointer exception.
Any idea what's going on here?
Remove your casts to (MockHttpServletRequest) and (boolean) so it looks like this
Mockito.when(oauthProviderMock.validate(Mockito.any(HttpServletRequest.class), Mockito.anyBoolean())).
thenReturn(new OauthStatus());
According to the anyObject API it will return null so you are probably seeing your NPE here.
According to the anyBoolean API it will return false so there should be no need to cast.
Work around is Mocked the method through programmatically by using anonymous class instead of Mockito.
ex:
oauthProvider = new OauthProvider(){
validate( HttpServletRequest req, boolean flag) throws Exception{
throw new RuntimeException();
}
};
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
StatusCodeException Vs. RuntimeException in GWT
I want to trigger RPC callback "onFailure" if the session expires in the server.
I created a custom RPC AsyncCallback that handles the "session expired" event from the server.
I overrode RemoteServiceServlet to validate the session prior to invoking the method. So basically, it is not the declared method that throws the exception but the custom RemoteServiceServlet. It still goes to the "onFailure" in the client async but the Throwable object is still of type "StatusCodeException" without the EXPIRED_SESSION_MSG message. Any ideas?
Custom RemoteServiceServlet:
public class XRemoteServiceServlet extends RemoteServiceServlet {
private final static String EXPIRED_SESSION_MSG = "ERROR: Application has expired session.";
#Override
protected void onAfterRequestDeserialized(RPCRequest rpcRequest) {
HttpServletRequest httpServletRequest = this.getThreadLocalRequest();
HttpSession session = httpServletRequest.getSession(false);
if (session != null) {
final String sessionIdFromRequestHeader = getSessionIdFromHeader();
if (!isNullOrEmptyString(sessionIdFromRequestHeader)) {
final String sessionId = session.getId();
if (!sessionId.equals(sessionIdFromRequestHeader)) {
throw new RuntimeException(EXPIRED_SESSION_MSG);
}
}
Custom AsyncCallback:
public class XAsyncCallback<T> implements AsyncCallback<T> {
private final static String EXPIRED_SESSION_MSG = "ERROR: Application has expired session.";
#Override
public void onFailure(Throwable caught) {
final String message = caught.getMessage();
if (!isNullOrEmptyString(message) && message.contains(EXPIRED_SESSION_MSG)) {
com.google.gwt.user.client.Window.Location.reload();
}
}
#Override
public void onSuccess(T arg0) {
}
/**
* Returns true if the string is null or equals to the empty string.
*
* #param string the string to test
* #return true if the string is empty
*/
private static boolean isNullOrEmptyString(String string) {
return string == null || "".equals(string);
}
}
See here for handling exceptions with GWT RPC.
An "expected failure" is an exception thrown by a service method that is declared in the signature of the service method. These exceptions are serialized back to the client.
"Unexpected expections" are errors that are not part of the service method's signature, or that result from SecurityExceptions, SerializationExceptions, or other failures within the RPC framework.
What you want is a checked exception, because you want to send it back to the client and do something about it. The RPC framework is in charge of catching it, serializing it and calling the onFailure method with the right exception. In order to do that, you need to follow its guidelines which are :
You need to specifiy in the service
signature that the exception can be
thrown.
The exception must be thrown
in the service implementation method.
What you're doing is throwing an unexcepted exception from some method that shouldn't even be throwing exceptions. So RPC doesn't know what really happened and sends back a generic message saying 'Hey, something unexpected happened, look at the server log'.
I understand that you want to check the session on every call. Your easiest option is to have a method to check that in your servlet implementation and call it from all your service methods.
Otherwise, you can try to override the GWT RPC framework by looking at the class
com.google.gwt.user.server.rpc.RPC
but that's pretty advanced stuff.
If you want to send exceptions via GWT-RPC you must use checked exceptions. RuntimeException is an unchecked exception so you can not use it in this case.
Create your own exception that extends Exception and implements Serializable. Also, you must indicate on methods declaration that this method might throw an exceptions:
In my GWT app. I overrode RemoteServiceServlet to check if the session is valid right before the service method is being called. I am trying to throw a RuntimeException("expired session") from the server and I would like the client to catch this exception from the asynccallback onFailure...
In the client I would like to:
Asynccallback:
#Override
public void onFailure(Throwable caught) {
final String message = caught.getMessage();
if (!isNullOrEmptyString(message) && message.contains("expired session")) {
com.google.gwt.user.client.Window.Location.reload();
}
}
However, in the client, the caught object is still a StatusCodeException and the message is still the default "...Exception in the server...". how can I override the exception at least the default message to compare if it was a session expired message I sent from the server?
thanks
Hi Gursel,
Here's my code:
-> Custom RemoteServiceServlet. I'm trying to "intercept" every method before it's invoked. I check the session and throw a RuntimeException if it's already expired. So basically, it is not the declared method that throws the exception but the custom RemoteServiceServlet. It still goes to the "onFailure" in the client async but the Throwable object is still of type "StatusCodeException" without the EXPIRED_SESSION_MSG message. Don;t know how to make this work. Thanks!
public class XRemoteServiceServlet extends RemoteServiceServlet {
private final static String EXPIRED_SESSION_MSG = "ERROR: Application has expired session.";
#Override
protected void onAfterRequestDeserialized(RPCRequest rpcRequest) {
HttpServletRequest httpServletRequest = this.getThreadLocalRequest();
HttpSession session = httpServletRequest.getSession(false);
if (session != null) {
final String sessionIdFromRequestHeader = getSessionIdFromHeader();
if (!isNullOrEmptyString(sessionIdFromRequestHeader)) {
final String sessionId = session.getId();
if (!sessionId.equals(sessionIdFromRequestHeader)) {
throw new RuntimeException(EXPIRED_SESSION_MSG);
}
}
All RuntimeExceptions thrown by Server side of gwt application has been wrapped as StatusCodeException if you did not declare them at your remote method declaration.
EDIT :
After, Thomas Broyer comment, I have learned that all exceptions (checked or unchecked) that are declared at remote method declaration are propagated to gwt client. Therefore all you have to do is just declare your remote method such as :
public void myRemoteMethod() throws RuntimeException;
The post looks too old, still here is the solution I have come up with. Override processCall(String payload) of RemoveServiceServlet, if the session is invalid execute the blow code else call super.processCall(payload).
//Pass the exception to Client
RPCRequest rpcRequest = RPC.decodeRequest(payload, this.getClass(), this);
onAfterRequestDeserialized(rpcRequest);
return RPC.encodeResponseForFailure(rpcRequest.getMethod(), new CustomException("Invalid Session!"),rpcRequest.getSerializationPolicy(), rpcRequest.getFlags());
All the GWT services are servlets so GWT serializes the custom exception and sends to client as string, we follow the same :)