GoogleCloudPlatform / gradle-appengine-templates

Freemarker based templates that build with the gradle-appengine-plugin
438 stars 205 forks source link

Add support for GAE modules #40

Closed GitTom closed 9 years ago

GitTom commented 9 years ago

App Engine Modules is a great, new-ish, feature of GAE, but for Java users it is a big pain to use in Eclipse.

Though Android/Cloud Studio uses the same 'module' terminology, I don't believe it has any templates that support this feature.

If it is possible, it would be great if there could be a template for created an EAR and sub-modules.

loosebazooka commented 9 years ago

What would you like to see? As a clarification, are you more interested in modules or EAR files? If it's just modules : adding modules is almost trivial, you simply add another backend and configure the appengine-web.xml to describe your module. Modules don't need to be deployed all at once (like the EAR formatted deployment).

The one problem here is that local development server runs wont load all modules in one test run, like it would otherwise with EARs. One workaround is using gcloud app run instead of appengineRun which might not be what you want.

If you really want an EAR formatted template, take a look at modules sample to see if that works for you.

GitTom commented 9 years ago

I'm a bit confused. I thought that the only way to use GAE/J modules is with an EAR (so it isn't one or the other)? Or at least, that's how it is with Eclipse.

I don't actually care about EAR's - I just want to take advantage of GAE multi-module feature. Are you saying that Android Studio supports multi-module and that it is super simple to use - if so, I'll switch to AS right away.

loosebazooka commented 9 years ago

Ah not quite. There is no explicit module support in Android Studio as that was not our initial concentration, it is a good feature to add in, unfortunately there is no timeline for it. I think it would be worth really exploring modules before making any switch. What I am saying is that it's not impossible to use modules in Android studio if you have an understanding of module configuration, and you can do so without dealing with EARs at all.

[https://cloud.google.com/appengine/docs/java/modules/#Java_Configuration]

As long as modules are all configured for the same <application>, they will be part of the same appengine project. You can ignore the appengine-application.xml file if you deploy each of your modules on their own.

Since this would be the normal workflow, I would suggest playing around with it first with a test project before moving your own project into it. I'm happy to answer any questions you might have on this thread.

GitTom commented 9 years ago

That sounds good enough. I'll give it a try, thanks!

GitTom commented 9 years ago

Okay I've now tried out AS and converted the project I'm working on to AS and multi-module.

For multi-module it does everything I need, and the conversion to multi-module is much simpler then with Eclipse. I found sharing code between modules to be diffcult and limited in AS, but hopefully that will improve.

I commented here also:
https://github.com/GoogleCloudPlatform/gradle-appengine-plugin/issues/186

Thanks, Tom.

loosebazooka commented 9 years ago

If you have common code for all your modules, you can try moving that code out in to it's own gradle subproject and include that project in each of your modules as a compile dependency.

In Android Studio, you can create a new "Java Library Module", put all your common code in there. Assuming your new module is called "javaLib"

You might need to edit the settings.gradle file to include "javaLib", so that gradle considers it part of the project.

include ':app', ':backend', ':javaLib'

Second you need to edit each of your backend's build.gradle to include the javaLib as a compile dependency. This makes the code available to the backend

dependencies {
   compile project(':javaLib')
}
GitTom commented 9 years ago

Yes, but my common code is more complicated then that. Some is plain Java, some has GAE dependencies, and some is Android code. And to make things worse, some of the dependencies are fulfilled by different libraries for different platforms, eg. my models are shared between Android & GAE modules, and they include objectify (the datastore library) calls so I created a stub library to allow my model classes to compile in my Android modules.

With Eclipse I was able to have a single tree of common source, and exclude folders (or occasionally files) as needed. With AS I've broken my common code into multiple shared source trees (eg. plain java, gae, android), but even this way, it means that all the eg. plain Java code shows up in all my projects. That's not a big deal since the unused code will be optimized out, but it pollutes my package namespace making it unclear which packages are part of which module.

loosebazooka commented 9 years ago

Another option is configurations in gradle. Take a look at : https://gradle.org/docs/current/userguide/dependency_management.html and see if that doesn't work for you, it might be a little bit of reading :.

Basically, you can define a bunch of configurations in a single subproject if you can add dependencies on those configurations instead of the whole project.

dependencies {
   compile project(path: ':javaLib', configuration: 'android-stuff')
}

This creates an artifact from your javaLib project that only includes what you've defined in the android-stuff configuration. It gives you the option of developing a lot of your code under a single subproject which while separating them as you please.

GitTom commented 9 years ago

Wow, that does look quite powerful and flexible. Artifacts would certainly address some of my issues.

I'm a bit hesitant to get into that now, as all this AS and gradle stuff is new to me, and I've now got my modules building using the system I describe above (with gradle sourceSets).

Do you know off-hand whether gradle would allow me to create one artifact of a library in which objectify calls (made by the code in the library) were resolved by the 'real' objectify library (which depends on app engine sdk) and another artificact in which the same code uses my stub library and be used in an Android module?

loosebazooka commented 9 years ago

Heh, most things are possible in gradle, it might be a little bit of work to get to the point you want. Presumably you'd have two configurations that share a sourceSet and build from there. When you're ready to try it out, I would try asking on stackoverflow or the gradle forums, they might have a much better idea on how to this.

GitTom commented 9 years ago

Ok. Thanks for your help and for telling me about artifacts - seems there's more to gradle then I realized!

hookenwu commented 7 years ago

@GitTom @loosebazooka After read all the conversation above and try to implement it in our project, I'am still confused with the solution without EAR implement, And the link of [https://cloud.google.com/appengine/docs/java/modules/#Java_Configuration] also missed. Can you please give me some advices? If there will be some code example is better...

Or I guess after the update of Google App Engine recently, the EAR solution is the only way to implement multiple service/module in Google App Engine?

Many TKS :)

loosebazooka commented 7 years ago

So EARs don't really translate well to app engine and I wouldn't recommend using them. They were provided as a convenience a long time ago and future tooling isn't expected to support them. If you want to do multiple modules, I would suggest you just develop and deploy them separately. Were you planning on using the dev appserver too?

hookenwu commented 7 years ago

:) Tks~ Finally I get the multiple service/module of app engine work without EARs and I think I caught the point of the pattern now :), the EARs solution indeed is not convenient compare to the current solution suggest by you. I think I am just mislead by this guide Converting Backends to Services

And I am currently not facing the issue when using the dev appserver with micro-services/multiple modules, but I think I would face this issue if the project evolve in future,. What should I do is like what you suggest before: run the command of gcloud app run instead of appengineRun, isn't it?

loosebazooka commented 7 years ago

Ideally you would be using the newer plugin at https://github.com/GoogleCloudPlatform/app-gradle-plugin which uses gcloud to deploy instead of the old sdk.

gcloud app run as a command is gone. If you have gcloud installed, make sure it is up to date, dev_appserver.py should be on your path or can be found in <gcloud-home>/bin/dev_appserver.py and you can use that to run multiple modules.

hookenwu commented 7 years ago

OK. That's perfect! Thanks for your support. I am updating my project to use this new plugin now. :)

loosebazooka commented 7 years ago

Any issues you're having there, please file against that repository.