Open choonchernlim opened 9 years ago
a simple approach should be to add a synchronized
to that method
public synchronized Set<ExchangeAppointmentBean> query(..)
[...]
seems to be a duplicate of #370 btw.
@serious6 Making the method synchronized is not the solution. The method creates a new ExchangeService
every time it is invoked and doesn't share any variables, so I don't see a problem with this code.
It looks like some internal HttpComponents stuff is shared between instances, where it shouldn't be.
Also see: http://stackoverflow.com/questions/29681969/ntlm-authentication-failing-in-multithreaded-application
I did stumble upon that SO post, but nothing I can do on my end to modify the connection manager.
I'm honestly not a big fan of using synchronized
at all, but right now I made the synchronized
block as small as possible to prevent the problem:-
private final Object lock = new Object();
@Override
public Set<ExchangeAppointmentBean> query(final String calendarEmail,
final LocalDate startDate,
final LocalDate endDate) {
final ExchangeService service;
final FindItemsResults<Appointment> findResults;
final ExchangeCredentials credentials = new WebCredentials("user", "pwd");
final FolderId folderId = new FolderId(WellKnownFolderName.Calendar, new Mailbox(calendarEmail));
final CalendarView calendarView = new CalendarView(startDate.toDate(), endDate.toDate());
final CalendarFolder calendarFolder;
try {
service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
service.setCredentials(credentials);
service.setUrl(new URI("https://hostname/ews/exchange.asmx"));
// problematic part using HttpClient
synchronized (lock) {
calendarFolder = CalendarFolder.bind(service, folderId);
}
findResults = calendarFolder.findAppointments(calendarView);
}
catch (Exception e) {
throw CommonUtils.createException(LOGGER, e, "Unexpected error occurred when querying Exchange Server");
}
....
service.close();
}
This works for me, but I'm not certain if I like this solution. Thank you.
It works only because making the method synchronized will eliminate all concurrency. I think this is a bug which should be fixed, however.
This is affecting me as well. It is making this version of the API unusable for me. I have been able to mitigate the issue caused by this error by writing code to retry following this error but I am worried this solution will not scale very well.
I, too, am affected by this issue. The API should support multiple instantiations of the ExchangeSevice that may be used concurrently, IMHO.
:+1:
@codewheeney I implemented a dirty fix for our issue. Would you please give my branch a try?
I am experience this issue as well, bottom of stack below for additional insight (which support other branch suggestions). I agree that the synchronized block is not a solution as I am attempting to mitigate performance issues by parallelizing the work on separate connections.
Caused by: java.lang.ArrayIndexOutOfBoundsException: 40 at org.apache.http.impl.auth.NTLMEngineImpl$NTLMMessage.addByte(NTLMEngineImpl.java:911) at org.apache.http.impl.auth.NTLMEngineImpl$NTLMMessage.addULong(NTLMEngineImpl.java:939) at org.apache.http.impl.auth.NTLMEngineImpl$Type1Message.getResponse(NTLMEngineImpl.java:1007) at org.apache.http.impl.auth.NTLMEngineImpl.getType1Message(NTLMEngineImpl.java:148) at org.apache.http.impl.auth.NTLMEngineImpl.generateType1Msg(NTLMEngineImpl.java:1628) at org.apache.http.impl.auth.NTLMScheme.authenticate(NTLMScheme.java:139) at org.apache.http.impl.auth.AuthSchemeBase.authenticate(AuthSchemeBase.java:138) at org.apache.http.impl.auth.HttpAuthenticator.doAuth(HttpAuthenticator.java:239) at org.apache.http.impl.auth.HttpAuthenticator.generateAuthResponse(HttpAuthenticator.java:202) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:262) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) at microsoft.exchange.webservices.data.core.request.HttpClientWebRequest.executeRequest(HttpClientWebRequest.java:292) at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.getEwsHttpWebResponse(ServiceRequestBase.java:720) at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.validateAndEmitRequest(ServiceRequestBase.java:639) at microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:62) ... 14 more
I've come across this same issue and adding a synchronized to the method or adding a synchronized block does not correct this issue. Have there been any fixes for this?
+1
+1
+1
Has anyone tried upgrading httpclient to 4.5.2 to fix the problem?
http://www.apache.org/dist/httpcomponents/httpclient/RELEASE_NOTES-4.5.x.txt [HTTPCLIENT-1715] NTLMEngineImpl#Type1Message not thread safe but declared as a constant. The issue was resolved in February 2016.
@indriesergiu I will hopefully be attempting to upgrade the httpclient dependency very soon and will report any results here.
@derylspielman Deryl, any luck on your end with the httpclient upgrade?
Just an idea: could implementing #423 help in this?
Hi guys, I've tested using the httpclient version 4.5.2 and it fixes the "The request failed. 40" issue, however, you will still run into "Connection is still allocated" issues (see https://github.com/OfficeDev/ews-java-api/issues/276). So at this point, if you use a new ExchangeService instance for each EWS request you can execute multiple EWS requests in parallel :)
+1. although hI have not had problems since switching to 4.5.2 seems to fix it.
This worked for me as well although I am using httpclient-4.5.3 and creating a new ExchangeService per e-mail.
When invoking the following code in 2 running threads:-
... I get this error from the try-catch block:-