How to run Google app engine endpoint methods from the backend - java

I have followed all the configuration steps for my WarmupServlet in my app engine project and I see it run at startup, but still I see my first endpoint call as a loading request which takes up to 25 seconds which is absolutely unacceptable. I need to be able to warm up each endpoint individually so that there will be no loading requests. (Apparently just setting up a warmp-up servlet is not enough.) So, my question is, how can I call a method in endpoints so that the endpoint is properly warmed up to serve from my WarmupServlet? I tried below with no success:
MyEndpoint me = new MyEndpoint();
me.getMyEntity(1L);
where
#ApiMethod(name = "getMyEntity")
public MyEntity getMyEntity(#Named("id") Long id) {
EntityManager mgr = getEntityManager();
MyEntity myEntity = null;
try {
myEntity = mgr.find(MyEntity.class, id);
} finally {
mgr.close();
}
return myEntity;
}

After adding the client endpoints jar file as a library, this properly warms up MyEndpoint from the Java backend:
NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
Myendpoint.Builder endpointBuilder = new Myendpoint.Builder(
HTTP_TRANSPORT,
JSON_FACTORY,
null);
endpointBuilder.setApplicationName("My App");
Myendpoint endpoint = endpointBuilder.build();
endpoint.getMyEntity(1L).execute();

Related

Spring boot mock method response

I need some help with unit tests. Our company has decided to start using TDD, and I'm supposed to implement that, but I've got very limited experience with unit tests in general, so I'm trying to cover some of the old code to get up to speed. That's when I got stuck with this:
public Analytics generateAnalytics(String id, String domain) {
List<Result> totalResults = new ArrayList<>();
for(String url : ANALYTIC_URLS) {
url += domain;
String scrubbedUrl = url.replace(API_KEY, "XXXXXXXXXX");
Audit audit = new Audit(id, scrubbedUrl);
try {
totalResults.add(new Result(getData(url, audit)));
} catch(Exception e) {
audit.setResponse(e.toString());
throw new Exception(e);
} finally {
auditRepository.save(audit);
}
}
return composeAnalytics(totalResults);
}
private List<Map<String, String>> getData(String request, Audit audit) throws Exception {
try (CloseableHttpClient client = HttpClients.createDefault()) {
CloseableHttpResponse response = client.execute(new HttpGet(request));
if(response.getStatusLine().getStatusCode() == 200) {
return readInputStream(response.getEntity().getContent(), audit);
} else {
throw new Exception(response.toString());
}
}
}
My issue is, when I wanna test the generateAnalytics method, the getData method goes and gets data from a live API that costs units per each request. Obviously I wanna stop this from bleeding out all our units during the testing. I've tried mocking the ClosableHttpClient like so:
#Mock
CloseableHttpClient client;
#InjectMocks
Service service;
#Test
void testTest() throws Exception {
when(client.execute(any())).thenReturn(mock(CloseableHttpResponse.class));
service.generateAnalytics("123", "no.com");
assertEquals(true, true);
}
This works when there's another service that needs to be mocked in one of my other tests, but in this case it still calls the API and drains our units. What should I do about this?
That's because your client mock is never used:
try (CloseableHttpClient client = HttpClients.createDefault()) {
Either mock HttpClients.createDefault() or , maybe better, inject the client into the service instead of creating on the fly.
Have you try to use MockMvc?
With MockMvc you can perform requests against a mocked servlet environment.
There won't be any real HTTP communication for such tests.
Official documentation: spring.io/testing-web

Spring CXF Soap Client OAuth2 Client Credentials

I want to consume a SOAP Web service which requires an OAuth2 authentication with client_credentials grant type.
From the documentation (http://cxf.apache.org/docs/jax-rs-oauth2.html#JAX-RSOAuth2-AdvancedOAuth2clientapplications) , I have found the BearerAuthSupplier which could be usefull. So I tried
#Bean
public CustomName customName()
{
final JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean();
factoryBean.setServiceClass(CustomName.class);
factoryBean.setAddress("");
final CustomName serviceClient = (CustomName ) factoryBean.create();
// Get the underlying Client object from the proxy object of service interface
final org.apache.cxf.endpoint.Client proxy = ClientProxy.getClient(serviceClient);
final HTTPConduit conduit = (HTTPConduit) proxy.getConduit();
final BearerAuthSupplier supplier = new BearerAuthSupplier();
supplier.setAccessTokenServiceUri("");
supplier.setConsumer(new Consumer("client-id", "client-secret"));
supplier.setRefreshEarly(true);
conduit.setAuthSupplier(supplier);
return serviceClient;
}
In the Authorization Header I had a Basic assertion (I wanted a Bearer). Plus, I had no possibility to set the scope of the token. I think there is something I missed ...
To get this working, I had to extend BearerAuthSupplier to somethink like this
public class CustomAuthSupplier extends BearerAuthSupplier {
private String accessTokenServiceUri;
public String getAuthorization(AuthorizationPolicy authPolicy,
URI currentURI,
Message message,
String fullHeader) {
ClientCredentialsGrant clientCredentialsGrant = new ClientCredentialsGrant("scope_needed");
clientCredentialsGrant.setClientId(this.getConsumer().getClientId());
clientCredentialsGrant.setClientSecret(this.getConsumer().getClientSecret());
WebClient wc = WebClient.create(this.accessTokenServiceUri, Collections.singletonList(new OAuthJSONProvider()));
ClientAccessToken at = OAuthClientUtils.getAccessToken(wc,clientCredentialsGrant);
this.setClientAccessToken(at);
return super.getAuthorization(authPolicy, currentURI, message, fullHeader);
}
public void setAccessTokenServiceUri(String uri) {
this.accessTokenServiceUri = uri;
super.setAccessTokenServiceUri(uri);
}
So far it works well, but I find it a bit complicated (and I'm not really sure of what i am doing). My question is : How to perform client credential grant with CXF when calling a Soap WS ?

Signing AWS HTTP requests with Apache HttpComponents Client

I'm trying to make HTTP requests to an AWS Elasticsearch domain protected by an IAM access policy. I need to sign these requests for them to be authorized by AWS.
I'm using Jest, which in turn use Apache HttpComponents Client.
This seems to be a common use case, but I can't find what should I do so Jest can sign all requests.
I think I found it! :)
This project seems to do exactly what I want : aws-signing-request-interceptor, described as "Request Interceptor for Apache Client that signs the request for AWS. Originally created to support AWS' Elasticsearch Service using the Jest client.".
Edit : I forked the project to fit my needs (Java 7, temporary STS credentials), and it works nicely.
Here is an example of usage (here without STS temporary credentials):
String region = "us-east-1";
String service = "es";
String url = "???"; // put the AWS ElasticSearch endpoint here
DefaultAWSCredentialsProviderChain awsCredentialsProvider = new DefaultAWSCredentialsProviderChain();
final AWSSigner awsSigner = new AWSSigner(awsCredentialsProvider, region, service, () -> new LocalDateTime(DateTimeZone.UTC));
JestClientFactory factory = new JestClientFactory() {
#Override
protected HttpClientBuilder configureHttpClient(HttpClientBuilder builder) {
builder.addInterceptorLast(new AWSSigningRequestInterceptor(awsSigner));
return builder;
}
};
factory.setHttpClientConfig(new HttpClientConfig.Builder(url)
.multiThreaded(true)
.build());
JestClient client = factory.getObject();
This doesn't work in case of Async request.
Update:
Ignore my previous comment. It works after adding interceptor for async requests too:
final AWSSigningRequestInterceptor requestInterceptor = new AWSSigningRequestInterceptor(awsSigner);
factory = new JestClientFactory() {
#Override
protected HttpClientBuilder configureHttpClient(HttpClientBuilder builder) {
builder.addInterceptorLast(requestInterceptor);
return builder;
}
#Override
protected HttpAsyncClientBuilder configureHttpClient(HttpAsyncClientBuilder builder) {
builder.addInterceptorLast(requestInterceptor);
return builder;
}
};

Retry java RestTemplate HTTP request if host offline

Hi I'm using the spring RestTemplate for calling a REST API. The API can be very slow or even offline. My application is building the cache by sending thousands of requests one after the other. The responses can be very slow too, because they contains a lot of data.
I have already increased the Timeout to 120 seconds. My problem now it that the API can be offline and I get a org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool exception.
In the case when the API ist offline, the application should wait and try again until the API is online again.
Can I achieve this in RestTemplate out of the box without building exception-loops on my own?
Thanks!
I had same situation and done some googling found the solution. Giving answer in hope it help someone else. You can set max try and time interval for each try.
#Bean
public RetryTemplate retryTemplate() {
int maxAttempt = Integer.parseInt(env.getProperty("maxAttempt"));
int retryTimeInterval = Integer.parseInt(env.getProperty("retryTimeInterval"));
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(maxAttempt);
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
backOffPolicy.setBackOffPeriod(retryTimeInterval); // 1.5 seconds
RetryTemplate template = new RetryTemplate();
template.setRetryPolicy(retryPolicy);
template.setBackOffPolicy(backOffPolicy);
return template;
}
And my rest service that i want to execute is below.
retryTemplate.execute(context -> {
System.out.println("inside retry method");
ResponseEntity<?> requestData = RestTemplateProvider.getInstance().postAsNewRequest(bundle, ServiceResponse.class, serivceURL,
CommonUtils.getHeader("APP_Name"));
_LOGGER.info("Response ..."+ requestData);
throw new IllegalStateException("Something went wrong");
});
You can also tackle this annotation-driven using Spring Retry. This way you will avoid to implement the template.
Add it to your pom.xml
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.2.RELEASE</version>
</dependency>
Enable it for your application/configuration
#SpringBootApplication
#EnableRetry
public class MyApplication {
//...
}
Guard methods that are in danger of failure with #Retryable
#Service
public class MyService {
#Retryable(maxAttempts=5, value = RuntimeException.class,
backoff = #Backoff(delay = 15000, multiplier = 2))
public List<String> doDangerousOperationWithExternalResource() {
// ...
}
}
Use Spring Retry project (https://dzone.com/articles/spring-retry-ways-integrate, https://github.com/spring-projects/spring-retry).
It is designed to solve problems like yours.
This approach saved my day.!!!Resilience saved my day.[Resilience retry][1]
RetryConfig config = RetryConfig.custom()
.maxAttempts(4)
.waitDuration(Duration.ofMillis(2000))
.failAfterMaxAttempts(true)
.build();
RetryRegistry registry = RetryRegistry.of(config);
HttpEntity<String> request =
new HttpEntity<>(body, headers);
Retry retry = registry.retry("notification-endpoint-"+System.currentTimeMillis());
AtomicReference<Integer> retries = new AtomicReference<>(0);
retry.getEventPublisher().onRetry(e -> {
log.info("Retrying here!!!. Count: {}", retries.updateAndGet(v -> v + 1));
}).onError(e->{
log.error("Failed to get to client.");
});
if(requestPojo.getMethod().equalsIgnoreCase("GET")) {
response = Retry.decorateCheckedSupplier(
retry,
() -> restTemplateConfig.restTemplate()
.exchange(url, HttpMethod.GET, request, String.class)).unchecked().get();
}
else if(requestPojo.getMethod().equalsIgnoreCase("POST")) {
response = Retry.decorateCheckedSupplier(
retry,
() -> restTemplateConfig.restTemplate()
.exchange(url, HttpMethod.POST, request, String.class)).unchecked().get();
}```
[1]: https://resilience4j.readme.io/docs/retry

How to use Google task API ?Initialize Tasks Get TaskList etc.?

I want to use google task api and want to get tasklist,update,delete,add etc.. and I found this link https://developers.google.com/google-apps/tasks/oauth-and-tasks-on-android where step by step procedure is given on that link the library which are given are deprecated.
That's why I have downloaded latetst library google-api-java-client-1.12.0-beta from here http://code.google.com/p/google-api-java-client/downloads/detail?name=google-api-java-client-1.12.0-beta.zip&can=2&q= and google-api-services-tasks-v1-rev5-java-1.12.0-beta from here http://code.google.com/p/google-api-java-client/wiki/APIs#Tasks_API and try the code given and similar to it but no luck not get anything i am successfully get accesstoken but not get anything and in the latest libs most of method are changes so how to inialize the Tasks and get TaskList,create,delete etc...... Not a single document i found related to updated library.
Hope for your regards.
Thanks.
This solution is for Server to server communication using OAuth 2.0
It is a three step process
Authenticate using OAuth 2.0
Get the com.google.api.services.tasks.Tasks service object
Get the required Task or TaskList
In this sample code it uses the domain id "abc.com" and the user is "user1#abc.com". For gmail users, please provide the gmailid (abc#gmail.com) as consumerkey and leave "xoauth_requestor_id" as gmailid
import com.google.api.client.http.*;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.tasks.*;
import com.google.api.client.auth.oauth.OAuthHmacSigner;
import com.google.api.client.auth.oauth.OAuthParameters;
public class GoogleConnection {
public Tasks setup() throws Exception {
com.google.api.services.tasks.Tasks tasks = null;
HttpRequestFactory httpRequestFactory = null;
HttpRequestInitializer httpRequestInitializer = null;
OAuthHmacSigner signer = new OAuthHmacSigner();
HttpTransport httpTransport = new NetHttpTransport();
OAuthParameters oauthParameters = new OAuthParameters();
final ArrayMap<String, Object> customKeys = new ArrayMap<String, Object>();
customKeys.add("xoauth_requestor_id", "user1#abc.com");
signer.clientSharedSecret = "secret_key_received_from_google";
oauthParameters.version = "2.0";
oauthParameters.consumerKey = "abc.com";
oauthParameters.signer = signer;
httpRequestFactory = createRequestFactory(httpTransport, oauthParameters, "20000", "20000");
httpRequestInitializer = httpRequestFactory.getInitializer();
tasks = new com.google.api.services.tasks.Tasks.Builder(httpTransport, new JacksonFactory(), httpRequestInitializer)
.setTasksRequestInitializer(new TasksRequestInitializer() {
#Override
public void initializeTasksRequest(TasksRequest<?> request) throws IOException {
#SuppressWarnings("rawtypes")
TasksRequest tasksRequest = (TasksRequest) request;
tasksRequest.setUnknownKeys(customKeys);
tasksRequest.setKey("keyapi_received_from_google_by_registering_your_app");
}
})
.setApplicationName("")
.build();
return tasks;
}
}
Getting Tasks from a Task List
Instantiate GoogleConnection class
public List<com.google.api.services.tasks.model.Task> getTasksFromTaskList(String taskListId) throws Exception {
com.google.api.services.tasks.Tasks tasksService = googleConnection.setup();
com.google.api.services.tasks.model.Tasks result = tasksService .tasks().list(taskListId).execute();
return result.getItems();
}

Categories

Resources