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

Опитвах се да се свържа с quickbooks онлайн от google app engine, като просто стартирах този прост код:

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 APIs извиквания от Google App Engine към Intuit? Според документите на Google изходящите сокети са за платени приложения и не са налични в приложения за разработка.   -  person Jarred Keneally    schedule 06.05.2013


Отговори (2)


AppEngine предоставя само ограничен API на сокет. По-специално, не можете да използвате повечето getsockopt/setsockopt повиквания, които във вашия случай извеждат грешката (setTcpNoDelay(..)).

QuickBooks SDK изглежда е със затворен код, така че няма начин да го заобиколите.

Актуализация:

От GAE Java SDK 1.8.1 е възможно да се използват методи за опции за сокет : те са no-op, но не хвърлят изключения, както преди:

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