App Engine: Having a web module and a endpoint module - java

I would like to have a web and an endpoint module.
I have this working in my dev environment largely following https://github.com/GoogleCloudPlatform/appengine-modules-sample-java .
However I can't get this working when hosted inside app engine. If I make the web module the default, I can't route to the endpoint module via dispatch.xml. This is because endpoints (apparently) need to live at /_ah/api and its not possible to route this away from the default module.
The other alternative is putting the endpoint module as the default module, however I don't then know how to route everything but /_ah/api/ to the web module. It seems that you can't route /* away from the default module.
EDIT: Note I want to have both modules running off of the same custom domain.
EDIT2: Note this is single page app. The front end module is purely html, css and js, which I want to talk to the endpoint module on the same domain.
Any way to solve this?

If the problem only resides in the routing, you can definitely have your default module with endpoints and a module 'website' for your frontend.
Then your dispatch file should look like that (python version, the Java one should be quite similar):
dispatch:
- url: "*/_ah/*"
module: default
- url: "*/*"
module: website
The dispatch file apparently sets the routing with a top to bottom priority so each request targeting the endpoints */_ah/* will be routed to the default module and the rest will go on the website module.
However if you have CORS issues, you can check in the handler configuration for static files or had the proper headers directly in your page handler code.

If the issue you have is splitting the traffic you should probably intercept all requests and look for the destination URL and divert accordingly. But i think your issue is actually accesing the endpoint deployed on a non default version.
You can deploy specific endpoints to specific (non default) versions of your app.
As stated in the official docs:
To access backend API versions that are deployed to non-default App Engine versions of your app, you must include the version specifier in the URL, like this: https://version-dot-your_app_id.appspot.com. For example, suppose your default app version is 1, but you want to access a backend API version deployed to App Engine app version 2; you would use this URL: https://2-dot-your_app_id.appspot.com.

The answer suggested by #Anhuin is good for your simpler purposes. But if you want to have totally independent modules, i suggest you to use subdomain mapping
Create a sub domain like api.domain.com for endpoints and web.domain.com for your regular frontend modules.
Map these in the dipatch.xml
<url>api.domain.com/*</url>
<module>endpointmod</module>
<url>web.domain.com/*</url>
<module>webmod</module>
I prefer this because '_ah' is used by appengine in multiple places like appstats, remote api and so on. This will be clearer to the people working in frontend also by calling the sub domains.

Related

classnotfoundexception in multi project web application

I'm working on a web application which is in the form of some war files for the JSF2 front end, some jar files for services, and some shared jars to call the services from the front end, eg
webLayer.war -> serviceUtilities.jar -> service.jar
My problem is that when I try to call a service from the front end using my service utilities (which use reflection to call a service class in a separate jar) I get a class not found exception.
I have worked around the problem by changing the scope of the dependencies in my web project pom.xml from provided to compile, but this is not ideal because I have to build all the relevant projects and then build them into my web layer as libraries.
What I want is to have my web layer wars and service layer jars completely separate so that if I change my service I only need to compile that project. But obviously I still want to be able to access the jars from my war.
Can this be done, and if so how?
Thanks in advance
I believe you are trying to achieve total decoupling between your projets but in an unorthodox way.
First of all, using provided, means that while the library is present at compile time, it will not be added to your deployable (the war in this case) because it is assumed to be present in the platform where you deploy. Think of a similar case when using the servlet api but you do not need it as an explicit dependency at runtime because your servlet container provides it. It does not give you decoupling but a way to prevent dependency duplication. So in your case, the web application and serviceUtilities.jar do not know anything about your service.jar at runtime, while they do at compile time.
It is very difficult to be able to access the jars directly as you say (even using reflection - it is still a binary dependency), while keeping the projects' lifecycle independent.
I think the best way to get total decoupling between layers is to use Rest + Json for communication. You may even be able to deploy your layers in separate nodes. As long as the services contract does not change (the rest urls in this case) you are safe to even switch between different implementations or expose multiple front ends
Your serviceUtilities in the web side will then be replaced by code that uses some rest client library and your service layer will also use some rest service provider to listen to your rest urls. Which technology you use depends on your preference and technology stack. Jersey is the reference implementation for JAX-RS, while you can also easily use spring controllers in the provider side.

Cloud Endpoints custom domain workaround

We have an AppEngine app with that we would like to use with Google Endpoints. We need to support a web client as well as mobile clients which is what makes Endpoints attractive to us since we can easily generate Android and iOS client APIs.
The problem is that cloud endpoints currently don't support custom domains, so our web client cannot directly communicate with the endpoints (the mobile clients do not have this issue).
Here is what we've tried already:
CORS requests from the client to the appspot.com domain. The problem with this is since our request do not meet the requirements for simple CORS (custom headers, cookies, etc.), a preflight request must be sent with every request, which slows everything down
Client makes request to our custom domain which in turn makes a request to the appspot endpoint. Again, the extra request is not good for performance
We've also tried setting up a duplicate Jersey REST API just for the web client. We double annotate all our methods (once for Cloud Endpoints and once for Jersey) and the web client accesses the Jersey API and the mobile clients access the Endpoints API. This works pretty well except that Jersey and Endpoints use different exceptions. So if we want to throw a 404 Endpoints exception that will mess up the Jersey response and vice versa.
Are there any other options? We want to use the power of Endpoints for generating mobile clients but also get around the custom domain limitation for the web client.
We ended up ditching Cloud Endpoints entirely and went with a pure Jersey REST API instead.
To deal with our need to generate mobile clients for the API, we annotated our API with Swagger. As an added bonus, Swagger seems to support more client generation than Cloud Endpoints and also makes it relatively easy to setup your own client generation from a template if your target language isn't directly supported.
Jersey + Swagger was not as easy to setup as Cloud Endpoints, but it is more customizable and allowed us to get around the custom domain restriction imposed by Cloud Endpoints.
Google Cloud Endpoints 2.0 now supports custom domains. If you are using Google Cloud Endpoints 1.0 you can migrate by doing the following:
Update your dependency to use the new artifact. In Maven, this looks
something like below:
com.google.endpoints endpoints-framework 2.0.0-beta.8
Remove the legacy dependency, which is the appengine-endpoints artifact.
Update the API entry point in your project web.xml file:
Rename all occurrences of SystemServiceServlet to EndpointsServlet.
Replace all occurences of the path /_ah/spi/* to the new required path /_ah/api/*
See:
https://cloud.google.com/appengine/docs/java/endpoints/migrating
https://code.google.com/p/googleappengine/issues/detail?id=9384
Easiest solution is to use reverse proxy.
For example if your application is http://myapp.appspot.com, create simple html page on http://myapp.com and redirect to http://myapp.appspot.com using javascript.
Index.html on http://myapp.com.
<html>
<head>
<script>
windows.location = http://myapp.appspot.com;
</script>
</head>
<body></body>
</html>
It has one more advantage: if you put your proxy page on another hosting (not appspot.com) your application ( http://myapp.appspot.com ) will be accessible from China.

Is Sitebricks compatible with GAE backends (Java)

I would like to know whether it is possible to host a Google App Engine backend servlet using Sitebricks. I am trying to do so in my GAE Java app -- frontend gets the backend URL using GAE's BackendService interface and send an HTTP Request -- but the HTTP response always returns with a 404 Not Found).
I would love to post some source code / configuration files, but I fell that it may be best for me to explain what I am doing. Basically, my servlet has been configured using Sitebricks in the same exact manner as my frontend servlets that are working perfectly (ie, using the #Service, #At and #Get annotation in the servlet classes and methods, plus configuring SitebricksModule in my app's global Guice Injector instance). I am using a dynamic backend instance, configured properly in backends.xml.
Does anyone have any hints on pairing Sitebricks with GAE Backends?
Yes Sitebricks works on GAE. I recommend the 0.8.8-SNAPSHOT version from sonatype's OSS repo for latest functionality. Otherwise the latest tested release is 0.8.7 from Maven Central. The only bit that doesn't work is requesting other websites from GAE using the Sitebricks Web Client.
Are you using GuiceServletContextListener? This is the best way to create an Injector. Also make sure your web.xml points to it and sets up GuiceFilter correctly (as per sitebricks.org docs).
Dhanji.
(maintainer, sitebricks)

Connect grails front with java REST backend

I have Java backend project with REST implementation which is a warfile,
I also have Grails as frontend, i can run theese two separeted projects on their own using tomcat,
but how do i configure the grails part so that i can use the java backend RESTfull webbservice within it,
do i have to make a war file from the java backend and import it to the grails frontend ? make a jarfile ?
if so, how do i do that ? or are there any other way to to this to make it work.
REST provides a way to access a service without having to link them explicitly.
RESTful applications use HTTP requests to post data (create = HTTP-POST, update = HTTP-PUT, read = HTTP-GET, delete = HTTP-DELETE
If you run the Java backend using Tomcat, can you access it from a browser?
i.e.
http://localhost:8080/backendservice/resource/1
(this will be a GET request.)
You need to make the http requests from your application.
A lot depends on how much control you have over the 2 apps and how they have been designed.
First choice is to create a service class in your grails app that communicates with the other app using REST. You could use something like Spring's RestTemplate. The data is then passed to the Controller layer and into your front end JSP/GSP.
If the RESTful application has been designed in such a way that the RESTful layer can be separated from the business layer, then you could add a jar of the business layer to the grails app as a dependency. In this case you would just change the Service class to talk to the jar instead of the RESTful service.
Another option is to have the browser talk to the REST layer directly using JavaScript. This should work as they come from the same server.

Server-wide functionality across several web applications

I need to perform pre- and post-processing of all incomming requests to a web server. The functionality is both url-level access restriction and language translation but also other special cases that need to be handled globaly.
Typically this can be achieved with servlet filters but when the number of web applications grow it becomes desirable not to bundle the filters with every application since all applications need to be rebuilt and re-deployed when making a change to a filter.
Instead I would like to install the filters globally on the server and I have found two possible solutions of which I'm not satisfied with any of them.
On Tomcat it is possible to deploy server-wide filters in the "lib" directory and configure the server web.xml to map them to incoming requests. The problem I see is that any filter dependencies also need to be deployed globally in the lib directory. From what I understand this can cause hard to solve dependency conflicts with installed applications. (Does Tomcat load the same library file into memory twice if they are in two web apps?)
Deploying the filters in a simple web application that mainly acts as a proxy would at least bundle the filters with their corresponding dependencies. This application can then be deployed on the server and take all incoming requests before forwarding them to the target application using the crossContext config parameter. (RequestDispatcher forward between Tomcat instances) However, this requires fiddling with the urls such that all links point to the "proxy".
Neither of these solutions seem to be satisfactory. They are both platform dependent since they rely on Tomcat. They also both seem to have possible problems and require special handling of dependencies.
What is the best practise when using server wide functionality?
This is my untested thought (so not a best practice) - which is a variation of option 2 in your list.
You can use Sitemesh (which is actually meant for decorating your multiple web apps with a common header/footer - but in this case dont use the header/footer).
Host the Sitemesh as a separate web app with crossContext = true.
Sitemesh will be invoked as a Filter for each web app, so the URLs that the end user sees will not change at all. But you will have to define the decortaor.xml for each web app.
You can write your actual Filter processor and chain it after the Sitemesh Filter. All requests will go to the Sitemesh app first - then to your Filter - then to the individual servlet within the web app.

Categories