Friday, April 27, 2018

Re: Discussion: gwt-user.jar-like uber jar for T.Broyer's multi-module project.



On Friday, April 27, 2018 at 4:34:25 PM UTC+2, vitrums wrote:
Any experienced developer tends to reuse existing components and organize his own code to allow reusability in future whenever it is possible. Division of labor further encourages a group of developers to physically split a big project into modules and work independently on each part. I think T.Broyer's multi-module project archetype for Maven introduces a great platform enabling these features and making versioning task look effortless.

However I personally start to have issues with the last part, when it comes to the release. Specifically, should I aggregate the build artifacts into one gwt-user.jar kind of unit? I know it's a broad topic, and there're multiple angles to look at this problem, one of which says "it's not Maven way" (though I start to doubt that I applied "Maven way" concept in the appropriate contex). Therefore I want to hear your advice regarding this matter and avoid reinventing the wheel. If there's a sample project already configured to do the similar task with grace, then I guess a link to github will be sufficient.

First, the archetypes are all about applications, not libraries. The archetypes will produce one WAR with the full application, that you can deploy effortlessly to any servlet container.

If you're going to talk about libraries, then let's step away from the archetypes and concentrate on the gwt-lib packaging from the net.ltgt.gwt.maven:gwt-maven-plugin (as that's what you're talking about).
 
Imagine you're developing gwt-user. Inside com\google\gwt\user folder you'll find client direcotry and a bunch of <module>.gwt.xml files such as User.gwt.xml, UI.gwt.xml, TextBox.gwt.xml. The latter contains a bunch of deferred binding instructions, e.g.:

  <!-- IE has a completely different TextBox implementation -->
 
<replace-with class="com.google.gwt.user.client.ui.impl.TextBoxImplIE8">
   
<when-type-is class="com.google.gwt.user.client.ui.impl.TextBoxImpl"/>
   
<when-property-is name="user.agent" value="ie8"/>
 
</replace-with>

User inherits UI and UI inherits TextBox. But then we also have a subfolder datepicker with DatePicker.gwt.xml and it's own client directory.

So my view on this is that you don't wanna ship datepicker.jar to your clients, but instead combine the components from all related projects and modules into one library.

--------------------------------------------------------------------------------------------------------------------------------

Further in the text I'm gonna present my hack to multi-module archetype build configuration based on maven-shade-plugin, so let's get into details.

There were three strong candidates to do this job: maven-jar-plugin, maven-assembly-plugin and maven-shade-plugin. However the latter was specifically made for:
- This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies.
- The Shade Plugin has a single goal: shade:shade is bound to the package phase and is used to create a shaded jar.

In multi-module structure of my sandbox project I have two gwt-lib packaged modules my-client-lib and my-client-lib-a. The task is to gather their build artifacts inside one jar. My solution was to create a subsidiary module sandbox-gwt (though it could as well be another project) with the same groupId as my-client-lib* and to include only such artifacts in the uber-jar. Making it this way automates the task of naming by exploiting ${project.groupId} and ${project.version} properties.

The real question is why you're developing my-client-lib and my-client-lib-a separately if your goal is to ship them as a single artifact (there can be use cases of course, but it's the exception rather than the rule).
If your lib does not have one single main gwt.xml entry point but really is more like a gwt-user.jar "set of libraries", then you'd probably better skip the gwt:generate-module and gwt:generate-module-metadata and put all your modules in src/main/resources (and not use src/main/module.gwt.xml).

But maybe please consider the future where J2Cl in GWT3 will transpile all source files from JARs, without any kind of filtering. You'd better have many small jars then, than a bigger jar containing several libs users won't necessarily all use.
 
But there's a set of techniques mentioned in different sources, which might do the task better?! Those include the use of:
- <profiles>

Don't use profiles, that's not what they're made for: https://www.cloudbees.com/blog/maven-profiles-and-%E2%80%9C-maven-way%E2%80%9D
 
- <executions>

I must say I don't understand what you're talking about here (i.e. how you'd use them here)
 
BOM parent to manage dependencies better. I think it also helps to keep versioning clean.

I'm not sure how this is related to the issue, but that can be useful to the users of the libraries yes.
 

--------------------------------------------------------------------------------------------------------------------------------

I also noticed, that gwt-maven-plugin can generate some code in <actual-module-name>.gwt.xml, such as adding

<inherits name="com.google.gwt.core.Core"/>


Let me be clear about this: I'm hesitating for about a year if not more about deprecating gwt:generate-module-metadata and setting generateInheritsFromDependencies to false by default in gwt:generate-module. I even hesitate sometimes about deprecating gwt:generate-module (and the use of src/main/module.gwt.xml) altogether.
This is probably what refrains me from finally tagging a 1.0 "final" release.
 
In the context of a large uber-jar such as gwt-user.jar if it could establish the crossreferencing between modules based only on Maven dependencies, that would be interesting. E.g. to put 

<inherits name="net.coolcode.gwt.mvp.MyCoolCodeAppA" />

inside MyCoolCodeApp.gwt.xml, if my-client-lib depends on my-client-lib-a.

--------------------------------------------------------------------------------------------------------------------------------

Lastly I'm curious, in a context of development of gwt-user project it seems that due to an unconventional for GWT applications module structure (src/main/module.gwt.xml not src/main/package/MyModule.gwt.xml) if we want to strictly follow the archetype's idiom, we must have one module per one <module>.gwt.xml, e.g. TextBox.gwt.xml. I'm not sure what I'm trying to ask, but is it the way?

See above about skipping gwt:generate-module and gwt:generate-module-metadata.
 
And since we manually manage <source path="client" /> in module.gwt.xml, is it so evil to put server-lib artifacts in the same uber-jar? 

See above about what it'd mean with J2Cl and GWT3.
Also, that means you're shipping your client-side classes and their sources into your server app. That could possibly make it quite heavier.

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment