GAE/J + Restlet + Backend + Cron Job + 405 Error: - google-app-engine

Hoping to get some help or direction with the following issue I am facing.
I am getting a 405 (method not allowed) error when using GAE backends with a cron job on the live system. The cron job started on the backend I defined, but it is throwing the 405 error after delegating the call to the target Restlet. The url route is as follows as per the logs.
http://backendname.appid.appspot.com/cronURL
My current configuration is as follows:
GAE/J: 1.6.1
RESTLET: 2.1 RC5
I've have done the following:
Defined the attachment of the cron url route to my java class in my Restlet application
I have backends.xml defined
Set my backend as public to see if that resolves the issue, but it didn't
I have cron.xml defined
Set url for cron job
Set the target as my backend instance name
Please let me know if you would like more information.
Thanks!

Have you marked up your RESTlet with the #Get annotation?
A cron job will invoke the specified URL using an HTTP GET. Other verbs (e.g., PUT, POST, DELETE) are not supported by cron jobs.

Related

Spring Boot application gives "405 method not supported" exception for only Angular/HTML/JSP resources

I have an application written with Spring Boot and AngularJS. When I try to hit a REST service as part of this application, I am able to hit it with POST method wherever POST is configured for request mapping.
But if I try to request AngularJS bind pages, I get a "405 method not supported" exception. So I try to create HTML and JSP pages too, which are not bound to Angular but still, I am getting the same exception.
Where can I start debugging this, and what is the likely reason?
i am sharing here furthere details about issue.
Basically this existing application created/developed with Jhipster, angularjs, Spring boot and spring security does not allow to access html/angularjs related resources with POST from outside. I will explain here what different scenarios work and what is not not working. 1.Postman trying to access base url trying to fetch index.html from same application- Give 405 Post method not allowed.2.Created an independent Test.html in same application and trying to access it from postman- Gives 405 Post method not allowed.3.Created a service which allows POST access in same application- Able to hit service from WSO2 IS IDP and also from Postman.4.Created a separate application on tomcat and provided as callback in WSO2 IDP with starting point for SSO from base url of existing application- Able to hit callback URL on tomcat server. Firefox shows that a POST request was generated for callback URL from WSO2 IS IDP to tomcat based application 5.Created a separate application with Angular js and Spring boot and provided as callback in WSO2 IDP with starting point for SSO from base url of existing application- Able to hit callback URL on tomcat server. Firefox shows that a POST request was generated for callback URL from WSO2 IS IDP to new application with Spring boot and Angularjs. This took me down to conclusion that one of three is causing this issue
1. Spring security generated from JHipster
2. Angularjs
3. Some CORS or other filter from Spring Security is causing this issue.
Till now we have tried to different debugging methods like
1. disable CORS,
2. in angularjs-resource.js enable POST for get operation,
3. In SecurityCOnfigurer, try to permit POST method for base URL or resolve it to GET in httpsercurity authorizerequest etc.
4. Also ignoring resources in websecurity.
Application stack for existing application which we are trying to implement SSO is as below
1. Angularjs 1.5.8
2. Springboot 1.5.9.release
3. WSO2IS 5.4.1
4. WSO2AM 2.1.0
5. JHipster
Let me know if any particular area which we might have missed to analyze or different methods to try.
Thanks,
Sandeep
Try to disable CSRF in security config
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
...
}
...
}
#SpringBootApplication
#Import({
...
SecurityConfig.class
...
})
public class SpringBootApp {
...
}

GCP CRON jobs failing with no logs

I am trying to set up a CRON job in a Google Cloud Platform. The job is showing up in the GCP console, although it is failing. There are no logs that reveal why it is failing. The schedule seems to be working ok, and I am able to manually run the job, although it also fails when initiated manually.
If I go to http://...../api/status/addit in the url bar, the job runs as expected.
There is a link to "View Logs" in on the task queues page where it shows my CRON job, but when I go to those logs they are completely empty.
Looking at the nginx request logs does not show any requests made to that url (or any requests for that matter). If I go to the url for the job manually, I can see those requests show up in the logs and everything that is supposed to happen happens so I know that endpoint is good.
Google App Engine Flexible environment, Python 3
Flask API
What other info can I provide? There are so many moving parts that I don't want to flood the question with irrelevant info.
cron.yaml:
cron:
- description: 'test cron job'
url: /api/status/addit
schedule: every 1 minutes
endpoint:
< some Flask Blueprint stuff initiates the "status" blueprint so that this url will resolve to /api/status/addit >
...
#status.route('/addit')
def add_to_file():
print('made it into the request')
from flask import Response
res = Response("{'foo':'bar'}", status=202, mimetype='application/json')
return res
I experienced the same issue with the same kind of configuration (GAE flexible, Python 3):
Cron fails with no logging.
Turns out it is a firewall issue: my default action was set to DENY.
According to the docs:
Note: If you define a firewall in the flexible environment, you must set firewall rules for both the 10.0.0.1 and 0.1.0.1 IP addresses to allow your app to receive requests from the Cron service.
Whitelisting 10.0.0.1 and 0.1.0.1 solved my issue.
Your urls don't match. Try:
cron:
- description: 'test cron job'
url: /addit
schedule: every 1 minutes
I ran into a similar problem when I was using SSL and a script to redirect users from http to https URLs (in my case SSLify). Google app cron seems to use the http version (at least for my flex app), so when my app was called by cron, it returned a 302 redirect to the https version which was interpreted as an error.
"A cron job will invoke a URL, using an HTTP GET" https://cloud.google.com/appengine/docs/flexible/nodejs/scheduling-jobs-with-cron-yaml
Thanks to https://stackoverflow.com/a/53018498/4288232 and comments that lead me to the solution.

Is it possible to delete data from Firebase by invoking servlets using Google App Engine cron jobs?

I have developed a simple chat application using AngularJs and Firebase. I have hosted this application on the Google app engine platform. Now, I want to delete the Firebase database containing chat messages on a schedule (every night).
Is there any way to achieve this using a servlet, so that it can be invoked as a cron job? Thanks.
PS: The firebase documentation has been given only for Android and I am new to this. SO, specifically looking for servlet code.
It's not entirely clear from your question or description what you need assistance with. This answer assumes you'd like a daily cron job to send a request to an App Engine handler which then deletes data from a Firebase database.
From the documentation, Firebase has a REST API. Therefore, data can be added, removed and updated using standard HTTP requests (GET, PUT, POST, PATCH, DELETE). Any application capable of issuing HTTP requests can make changes to the data when properly authenticated and authorized.
Given your request to use a cron job and Java servlet on App Engine, I'd advise the following:
Define a cron job that issues requests to a specific URL in your cron.xml
<cron>
<url>/firebase_cleanup</url>
<description>Delete all chat messages of the day</description>
<schedule>every day 23:00</schedule>
</cron>
Deploy a servlet that will handle such requests and issue the appropriate HTTP request to Firebase. In your case, it should issue a DELETE request. This can be done using HttpURLConnection.
URL url = new URL("firebase-url-formatted-for-delete-request");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("DELETE");
int responseCode = connection.getResponseCode();
// Act upon responseCode accordingly
Note that the above servlet code does not include the authentication you'll need to issue the DELETE request. That will require your Firebase secret or a generated token. As I do not have a Firebase account, I cannot test the above so it will likely require some modifications.

A simple Cron job on frontend servers and no backends. Fails

I configured a simple cron job available at secure(admin only) path /cron?method=sendMail to send an email once daily. The servlet at the endpoint of the url is a jsp file which has the code to send the email.
This is tested through the frontend with the full url and it works.
I do not have any backend servers configured. Only frontend instances with 1 resident and dynamics.
The issue is that cron triggers successfully but the request fails with the following message.
0.1.0.1 - - [17/Nov/2013:01:07:44 -0800] "GET /cron?method=sendMail HTTP/1.1" 503 364 - "AppEngine-Google; (+http://code.google.com/appengine)"
This request is getting retried continuously and keeps failing.
The complete url however works. What is wrong with the setup? what am I missing?
Also, how do I stop the retries?
The cron entry I use goes like
<cron>
<url>/cron?method=sendMail</url>
<description>Send mail</description>
<schedule>every mon,tue,wed,thu,fri,sat,sun 11:30</schedule>
<timezone>Asia/Calcutta</timezone>
</cron>
The issue was resolved using the following tip from the documentation to secure the url
Requests from the Cron Service will also contain a HTTP header: X-AppEngine-Cron: true
The X-AppEngine-Cron header is set internally by Google App Engine. If your request handler finds this header it can trust that the request is a cron request. If the header is present in an external user request to your app, it is stripped.

GAE cloud endpoints - Api not updating after deploy

I'm starting to use cloud endpoints in my GAE project but have been running into issues with the api not updating on the server.
localhost:8888/_ah/api/explorer is ok.
But when I deploy, nothing changes.
myapp.appspot.com:8888/_ah/api/explorer is bad
Further investigation shows the url end points update
example: https://myapp.appspot.com/_ah/api/myapp/v1/foo/list
But the loaded client api is still incorrect.
example: gapi.client.load('myapp', 'v1', callback, url);
gapi.client.myapp.foo.list();
If I changed the call from foo/list to foo/list2, the rest url would update, the api package would not.
I'll try to cover the two cases people could run into:
Client Side:
The Google APIs Explorer web app aggressively caches, so you'll need to clear your cache or force a refresh when you update your API server side to see the changes in the client.
Server Side (In Deployed Production App Engine App):
If you're having deployment issues, there are two places to look when debugging:
Check your Admin Logs (https://appengine.google.com/adminlogs?&app_id=s~YOUR-APP-ID) after deployment. After a successful deployment of your application code, you should see the message:
Completed update of a new default version
and shortly after that you should see:
Successfully updated API configuration
If you this message indicates the API configuration update failed, you should deploy again. If said error is persistent, you should notify us of a bug. If you don't see any message about your API configuration, you should check that the path /_ah/spi/.* is explicitly named in your routing config (app.yaml for Python, web.xml for Java).
Check your Application Logs (https://appengine.google.com/logs?&app_id=s~YOUR-APP-ID) after deployment. After the deployment finishes, Google's API infrastructure makes a request to /_ah/spi/BackendService.getApiConfigs in your application so that your API configuration (as JSON) can be registered with Google's API infrastructure and all the discovery-related configs can be created. If this request does not complete with a 200, then your API changes will not show up since Google's API infrastructure will have nothing to register.
If you are consistently getting a 302 redirect for requests to /_ah/spi/BackendService.getApiConfigs, it is because you (or your generated API config) have specified a "bns adapter" that uses http: as the protocol in your API root, but your web.xml (Java) or app.yaml (Python) is required that paths through /_ah/spi are secure. This will make requests using http: as the protocol be redirected (using 302) to the same page with https: as the protocol. This was discussed on the Trusted Tester forum before going to Experimental.
This is what happened to me.
I tested my endpoint on localhost and it worked fine.
I deployed my endpoint on appspot and when I made requests to it I received in the browser the message 'Not found'.
So I looked in the logs and when I made requests to the endpoint I saw a 404 http error code on favicon file. And in effects I forgot to put that file in my deploy.
So I redeployed my war with the favicon file, the 404 http code disappeared and the endpoint worked fine on appspot too!
I realize that this may sound silly, but it is what I experienced. (I apologize for my poor english)
I noticed that if you upload your app for the first time without the following in your web.xml:
<security-constraint>
<web-resource-collection>
<url-pattern>/_ah/spi/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Then your bns adapter will be set as http going forward. When I add the above afterwards, I get 302 http code on /_ah/spi/BackendService.getApiConfigs and the endpoints never update.
So now I have reverted to not use https on /_ah/spi and my endpoints are updating. I guess for those that see their endpoints not being updated revert back to the first configuration they had for ssl on /_ah/spi/.
Yaw.
I had the same error Not Found (the 404 error code) when I was calling my API using this URL
https: // MY_APP_ID.appspot.com / _ah / api / MY_SERVICE / v1 / user
I tried everything and finally fixed it by removing the discovery files from WEB-INF and kept only MY_SERVICE-v1.api and then redeployed the API. It works fine now.
I was also getting stale API discovery doc after deploying new version, it took a couple of minutes for GAE to start serving the new one to me.
I had the same problem, and I checked the admin logs, other logs etc... but still my API wasn't updating to the latest version.
So I decided to check in the API code for the last method I had written (I am writing in Java 7). And I found out that GAE doesn't like statements like:
if (!blocked){ .... }
I switched that to:
if (blocked == false) { ... }
And it worked like a charm. So by the looks of it, GAE scans the new API methods and doesn't accept some shortcuts.

Resources