Hi guys, Just wanted to make sure you guys see the ThreadSafety wiki page we posted: https://code.google.com/p/google-api-ads-java/wiki/ThreadSafety. Of particular note is that AdWordsService is no longer considered heavy-weight.
With respect to OAuth credentials, the library will try to refresh the token if we have a expiry time. One option, if you don't want to store expiry time, is to always call .refresh() after constructing the Credentials object from a stored refresh token. You also might want to look into the various CredentialStore (or implement your own) for persisting this info (this is the recommended approach). It's entirely possible to just persist the refresh token yourself and then construct a session and call .refresh() on the Credentials in the thread before using it. - Kevin Winter AdWords API Team On Wednesday, October 10, 2012 4:15:37 PM UTC-4, j.e.frank wrote: > > That's not quite what I had in mind, because I have a lot of accounts to > deal with and I don't want to create all the service objects ahead of time. > I am planning to have one AdWordsServices object, wrapped to ensure thread > safety. I will create the service objects on demand using this object, and > throw them away after the call(s) complete. I'm still working on how I > plan to use the OAuth2 credential(s) to create AdWordsSessions. Since I > have so many accounts, I don't want to have a cache of sessions or anything > per account, although I could create a "session pool" if it turns out to be > expensive to make AdWordsSessions. > > On Wednesday, October 10, 2012 3:29:53 PM UTC-4, Oliver wrote: >> >> Agreed. Best practices would be of great help. >> >> I guess your solution of a 'singleton' AdwordsServices would work. Is >> the following what you had in mind: >> >> - The only time we need AdwordsServices is to create the service objects. >> The service objects can be created at any time during the long lived >> process. >> - We create only one global copy of the AdwordsServices object. >> - The first time access to an account is needed, we use the global >> AdwordsServices (in a thread safe way) to create all the service objects we >> will need for the whole duration of the process. >> - We cache the service objects instead of AdwordsServices at the account >> level, and hence no need to use AdwordsServices again. >> >> Oliver >> >> >> On Wednesday, October 10, 2012 5:00:38 PM UTC+1, j.e.frank wrote: >>> >>> My read was the same as yours: AdWordsServices doesn't retain the >>> session. We have thousands of accounts so I don't want to have one per >>> account if it's a "heavyweight" object as indicated in the migration guide. >>> So that's why I came up with idea of a wrapper object that will ensure >>> thread safety. >>> >>> But I think this back-and-forth you and I are having is indicative of >>> the need for some additional examples or documentation of best practices, >>> so that each person doesn't have to puzzle it out and invent a solution. >>> >>> On Wednesday, October 10, 2012 7:30:13 AM UTC-4, Oliver wrote: >>>> >>>> I need to correct myself. AdwordsServices itself does not hold a >>>> reference to the session. It's the actual service objects generated from >>>> AdwordsServices that do. e.g. >>>> >>>> CampaignServiceInterface campaignService = adWordsServices.get(session, >>>> CampaignServiceInterface.class); >>>> >>>> >>>> But AdwordsServices is not thread safe, so caching it at the account >>>> level instead of the appliaction (multiple accounts) level will make >>>> things >>>> easier. >>>> >>>> Oliver >>>> >>>> >>>> On Wednesday, October 10, 2012 11:35:54 AM UTC+1, Oliver wrote: >>>>> >>>>> Here is what I think: >>>>> >>>>> The AdwordsServices object holds a reference to the AdwordsSession >>>>> object. Since AdwordsSession is linked to one account ID only, you need >>>>> to >>>>> be very careful not to use AdwordsServices across accounts without >>>>> switching the session. >>>>> >>>>> What we do is create and cache a copy of AdwordsServices and >>>>> AdwordsSession for each account. The objects are re-used for all calls on >>>>> an account. We're careful not to use multithreads when accessing the >>>>> Service API for an account (AdwordsServices). Using multi-threads when >>>>> downloading reports is fine. >>>>> >>>>> Refreshtoken: my understanding is that the client libraries will take >>>>> care of automatically refreshing the OAuth2 token if needed (however, I >>>>> have not tested this yet). So, in theory, all you need to do is persist >>>>> the refresh token and keep using it until the end user revokes access. >>>>> >>>>> If anyone has better ideas than the above please let us know. >>>>> >>>>> Oliver >>>>> >>>>> >>>>> >>>>> Tuesday, October 9, 2012 7:28:45 PM UTC+1, j.e.frank wrote: >>>>>> >>>>>> I had seen that post, which is what prompted me to post my own. I am >>>>>> trying to better understand how multiple threads should/can share >>>>>> objects. >>>>>> I don't want to go the route of "each call creates its own set of >>>>>> objects", if there's a more efficient way to do things. >>>>>> >>>>>> As an example, consider the AdWordsServices class, which is new (to >>>>>> me). The migration guide says "The AdWordsServices object is fairly >>>>>> heavyweight and should be instantiated once and reused as much as >>>>>> possible." It is not thread-safe, but it doesn't retain any state. My >>>>>> conclusion is that if I make a singleton AdWordsServices object for use >>>>>> throughout my code, as long as I make sure no two threads are calling >>>>>> adWordsServices.get at the same time, that should be more efficient than >>>>>> creating a new one every time I need to make an AdWords API call. In >>>>>> order >>>>>> to achieve thread safety, I will probably wrap the AdWordsServices >>>>>> object >>>>>> inside my own singleton object, with a synchronized "get" method that >>>>>> passes through to the wrapped AdWordsServices object. That's an example >>>>>> of >>>>>> a best practice that I'm looking for. >>>>>> >>>>>> As for the OAuth2 credential, I have managed to create a valid one >>>>>> from a saved refresh token, by building the credential and then calling >>>>>> credential.refreshToken(). I'm still trying to figure out whether I >>>>>> need >>>>>> to do this refresh step or if it would happen automatically, and also >>>>>> whether calling refreshToken() is going to invalidate any >>>>>> AdWordsSession(s) >>>>>> that are currently using the credential before it got refreshed. I'm >>>>>> going >>>>>> to write some tests, and once I understand the credentials, tokens, and >>>>>> AdWordsSessions better, I will be able to come up with a coding strategy >>>>>> that fits my use case (long-lived services, all with the "same" login). >>>>>> But if there are examples already that match my use case, it will be a >>>>>> big >>>>>> time-saver and also make it more likely that I don't misunderstand how >>>>>> things work, or come up with a flawed solution. >>>>>> >>>>>> On Tuesday, October 9, 2012 1:42:49 PM UTC-4, Oliver wrote: >>>>>>> >>>>>>> You will need to persist the refresh token and account ID so your >>>>>>> services can resume on their own in case of a restart. You can ceate >>>>>>> valid >>>>>>> AdwordsSession and AdwordsServices on the fly if you have these two >>>>>>> fields. >>>>>>> >>>>>>> Also, this might be of help: >>>>>>> >>>>>>> https://groups.google.com/forum/?fromgroups=#!topic/adwords-api/zf0slvrjkMs >>>>>>> >>>>>>> Oliver >>>>>>> >>>>>>> On Tuesday, October 9, 2012 5:08:03 PM UTC+1, j.e.frank wrote: >>>>>>>> >>>>>>>> I am trying to migrate to v201209 from v201109. I have several >>>>>>>> long-lived services that use the AdWords API on behalf of my MCC >>>>>>>> account, >>>>>>>> for example to run reports, to get ad details, and so forth. I'm >>>>>>>> trying to >>>>>>>> understand how I should be using the new session/service objects, such >>>>>>>> that >>>>>>>> more than one thing can be happening at once, but that I don't create >>>>>>>> a new >>>>>>>> session or service object when I don't need to, and also that I use my >>>>>>>> OAuth2 tokens appropriately (refresh if necessary but not every time I >>>>>>>> need >>>>>>>> to make a call). I've seen several pieces of example code, but they >>>>>>>> are >>>>>>>> self-contained so they always get a new session, new service object, >>>>>>>> refresh the OAuth token, etc. Are there any examples more suitable for >>>>>>>> long-running services that will be invoked from time to time? >>>>>>> >>>>>>> -- =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ Also find us on our blog and discussion group: http://adwordsapi.blogspot.com http://groups.google.com/group/adwords-api =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ You received this message because you are subscribed to the Google Groups "AdWords API Forum" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/adwords-api?hl=en
