QuickBooks НЕ работает на Google App Engine

Я пытался подключиться к быстрым книгам онлайн из механизма приложений Google, просто запустив этот простой код:

OAuthCredentials oauthcredentials = new OAuthCredentials(consumerKey, consumerSecret, accessToken, accessTokenSecret);

PlatformSessionContext context = new PlatformSessionContext(oauthcredentials, appToken, PlatformServiceType.QBO, realmID);

QBCustomerService customerService = QBServiceFactory.getService(context, QBCustomerService.class);

QBIdType idType = new QBIdType(context);

idType.setValue("2");

QBCustomer c = customerService.findById(context, idType);

System.err.println(c.getName());

и он всегда выдает мне эту ошибку:

com.intuit.ds.qb.IDSException: java.net.SocketException: Operation failure: Unknown error.
    at com.google.appengine.api.socket.SocketApiHelper.translateError(SocketApiHelper.java:105)
    at com.google.appengine.api.socket.SocketApiHelper.translateError(SocketApiHelper.java:118)
    at com.google.appengine.api.socket.SocketApiHelper.makeSyncCall(SocketApiHelper.java:82)
    at com.google.appengine.api.socket.AppEngineSocketImpl.setSocketOptionAsBytes(AppEngineSocketImpl.java:229)
    at com.google.appengine.api.socket.AppEngineSocketOptions$BooleanCheckFunction.apply(AppEngineSocketOptions.java:168)
    at com.google.appengine.api.socket.AppEngineSocketOptions$Option.validateAndApply(AppEngineSocketOptions.java:358)
    at com.google.appengine.api.socket.AppEngineSocketOptions$Option.validateAndApply(AppEngineSocketOptions.java:373)
    at com.google.appengine.api.socket.AppEngineSocketImpl.setOption(AppEngineSocketImpl.java:144)
    at com.google.appengine.api.socket.AppEngineSocketImpl.setOption(AppEngineSocketImpl.java:171)
    at java.net.Socket.setTcpNoDelay(Socket.java:950)
    at sun.security.ssl.BaseSSLSocketImpl.setTcpNoDelay(BaseSSLSocketImpl.java:330)
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.prepareSocket(DefaultClientConnectionOperator.java:222)
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:153)
    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149)
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121)
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:573)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:425)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)
    at com.intuit.ds.qb.IDSRestClient.sendRequest(IDSRestClient.java:557)
    at com.intuit.ds.qb.IDSRestClient.get(IDSRestClient.java:160)
    at com.intuit.ds.qb.qbo.QBOService.getQBOBaseURI(QBOService.java:24)
    at com.intuit.ds.qb.IDSRestClient.setServiceTypeProperty(IDSRestClient.java:698)
    at com.intuit.ds.qb.qbo.QBORequestCreator.doIDSGet(QBORequestCreator.java:41)
    at com.intuit.ds.qb.qbo.AbstractQBOBaseDataService.findById(AbstractQBOBaseDataService.java:185)
    at com.intuit.ds.qb.qbo.QBOCustomerService.findById(QBOCustomerService.java:153)
    at com.xyz.server.tasks.SyncCustomerTask.runMethod(SyncCustomerTask.java:85)
    at com.xyz.server.tasks.SyncCustomerTask.run(SyncCustomerTask.java:33)
    at com.google.apphosting.utils.servlet.DeferredTaskServlet.performRequest(DeferredTaskServlet.java:136)
    at com.google.apphosting.utils.servlet.DeferredTaskServlet.service(DeferredTaskServlet.java:99)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
    at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:125)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.utils.servlet.JdbcMySqlConnectionCleanupFilter.doFilter(JdbcMySqlConnectionCleanupFilter.java:57)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:266)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
    at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:146)
    at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:438)
    at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:480)
    at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:487)
    at com.google.tracing.TraceContext.runInContext(TraceContext.java:774)
    at com.google.tracing.TraceContext$DoInTraceContext.runInContext(TraceContext.java:751)
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:342)
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:334)
    at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:484)
    at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:251)
    at java.lang.Thread.run(Thread.java:722)

где в com.xyz.server.tasks.SyncCustomerTask.runMethod(SyncCustomerTask.java:85) находится строка findbyId("2") в моем коде. Любые предложения, как обойти эту проблему? Любая помощь будет действительно очень признательна


person user2354981    schedule 06.05.2013    source источник
comment
Можете ли вы совершать вызовы REST API из Google App Engine в Intuit? Согласно документам Google, исходящие сокеты предназначены для платных приложений и недоступны в приложениях для разработки.   -  person Jarred Keneally    schedule 06.05.2013


Ответы (2)


AppEngine предоставляет только ограниченный Socket API. В частности, вы не можете использовать большинство вызовов getsockopt/setsockopt, которые в вашем случае вызывают ошибку (setTcpNoDelay(..)).

QuickBooks SDK, похоже, имеет закрытый исходный код, поэтому его невозможно обойти.

Обновление:

Начиная с GAE Java SDK 1.8.1 можно использовать методы параметров сокета. : они не работают, но они не генерируют исключения, как раньше:

The Sockets API now allows client code to call get/set options against sockets. Previously, calls raised "Not Implemented" exceptions. When java.net.Socket.get<option>() is called, a mock value is returned, calls to set<option>() will be silently ignored.

person Peter Knego    schedule 06.05.2013

Я так благодарен, что вы опубликовали этот вопрос. Я несколько дней бился головой о стену с той же проблемой, за исключением того, что я разрабатываю свое приложение Google на языке Go, а не на Java. НО Я СДЕЛАЛА ЭТО РАБОТОЙ! Надеюсь, что мое решение поможет и вам. По сути, вместо службы сокетов я использую службу URL Fetch, задокументированную для Java здесь: https://developers.google.com/appengine/docs/java/urlfetch/

Я ничего не знаю о некоторых деталях вашего исходного сообщения (я не разрабатывал Java и не знаком ни с QBServiceFactory, ни с OAuthCredentials). Поэтому я не уверен, насколько вы контролируете, как он на самом деле отправляет запросы в QB. Но в худшем случае, я думаю, вы сможете написать свои собственные функции для замены QBServiceFactory (что мне пришлось сделать в Go), и если вы убедитесь, что они используют службу URL Fetch вместо сокетов, вам может быть лучше удача.

Как я уже сказал, я очень благодарен за ваш вопрос, потому что я не думаю, что иначе наткнулся бы на свой ответ, так что спасибо!

person Blair Connolly    schedule 26.08.2013