GWT hosted mode in multiproject maven setup - java

I have a multimodule maven setup for my project, made of 5 modules, which includes a GWT webapp.
It is also an eclipse multiproject workspace, so I created an additional project, only containing a pom, which lists the other projects (sibling on the file system) as children modules.
I'm also a new maven user, so I might be doing something wrong. =)
The gwt module uses the following plugin
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.4.0</version>
<executions>
<execution>
<goals>
<goal>generateAsync</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<hostedWebapp>war</hostedWebapp>
<runTarget>GWT.html</runTarget>
</configuration>
</plugin>
When I run mvn package on the pom project I get the expected behaviour: projects are build in the correct order, and the war is fine.
When I run mvn gwt:run, though, maven tries to find a gwt app on each module, failing on the first one (the parent) which doesn't even declare nor manage the gwt plugin.
If I run mvn -fn gwt:run, the build fails on each other project, finally finding a gwt app on the gwt module, and displaying it.
How do I correctly run the app on hosted mode? Is this the correct behavior?
I do not want the GWT module to be the parent module (if it's possible), because the project has multiple target platforms, producing the gwt web frontend, a Java executable jar backend and in the future also an Android app, and shares most parts of the code (not only the model). Is a single pom structure recommended for such a setup, or am I failing at maven?
Are profiles what I need? If I do, should I declare the same profile id on each module? How would I prevent the trigger of gwt:run command on them anyway?
What should the setup of such a project be? Is this the correct setup?
Additional information
Modules are
pom: declares modules model, logic, analyze, gwt, tests
model: no dependencies
logic: no dependencies
analyze: depends on model, logic
gwt: depends on model, logic
tests: depends on model, logic, analyze, gwt (contains global tests,
not unit tests)
If I run gwt:run on the gwt module i get the error
Could not resolve dependencies for project
djjeck.gwt:djjeck.gwt:war:0.0.1-SNAPSHOT:
Could not find artifact djjeck.model:djjeck.model:jar:0.0.1-SNAPSHOT
This is from djjeck.gwt/pom.xml
<dependency>
<groupId>djjeck.model</groupId>
<artifactId>djjeck.model</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
A com.model-0.0.1-SNAPSHOT.jar is inside the war lib folder, both packed and unpacked, and also inside djjeck.model/target.

Go to the webapp module and then run mvn gwt:run.
You may use profiles to speed up compilation time: one profile could only gwt compile for gecko and english +draftCompile for example.
Have a look at maven GWT plugin multi-module setup if you're still having problems.

As I was also struggling with GWT dev mode and a Maven project with multiple sub-modules/projects, I created an example and uploaded it to GitHub. You can find it at:
https://github.com/steinsag/gwt-maven-example
The readme on aboves page shows how to run it via Maven. Features of this example are:
multiple modules
not using GWT's embedded Jetty, but an own Tomcat7 server
startup of Tomcat7 and GWT hosted mode possible via documented Maven commands
I hope this helps a bit to have at least a working example to start from.

Related

JavaFX Maven project in IntelliJ. JavaFX runtime components are missing only in IntelliJ. JAR through mvn package executes without issues

I have a Java Project with Spring Boot and JavaFX added through maven. The code compiles and even i can execute the fat jar without the JavaFX SDK in the computer. But when I try to execute it in IntelliJ it results in
Error: JavaFX runtime components are missing, and are required to run this application
I have seen this output in many questions and in most of those cases the jar wasn't built at all or code compilation failed.
But in this scenario the mvn package works with no errors and I can execute the JAR with java -jar <jar_name> to cross out the fact that I might have the javafx sdk installed somewhere I tried it in a VM with only the JRE installed.
pom.xml
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11.0.2</version>
</dependency>
As for plugins spring-boot-maven-plugin and maven-compiler-plugin.
Attempted Solutions
--1--
I tried the solution which said to add the
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.6</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<mainClass>com.example.demofx.Starter</mainClass>
</configuration>
</execution>
</executions>
</plugin>
But what it does is add the ability to run with: mvn clean javafx:run
The need to execute with IntelliJ is to debug the code because Debugging with souts isn't efficient.
--2--
Trying to module build with a module-info.jar with following
module com.example.demofx {
requires javafx.controls;
requires javafx.fxml;
// all other required modules including spring
opens com.example.demofx to javafx.fxml;
exports com.example.demofx;
}
This might have worked but due to some of old dependencies not working properly with modularized build this results in lots of breaking changes to the codebase.
Edit:
Missed to mention the environment
JDK - 11.0.8
IntelliJ IDEA - 2021.2.2
Added second solution tried.
This is more a troubleshooting and research guide than an actual fix. Fixes for environmental issues are difficult to provide in a StackOverflow context. However, if you study the information here, it might help you fix your project.
Recommended troubleshooting approach
Use the Intellij new JavaFX project wizard. Ensure that it works in your environment, then gradually add components from your current project into the working project, checking that everything still works after each small addition.
Debugging when executing via the JavaFX maven plugin
I think the above recommendation is the preferred approach, however, you can alternately get the following to work:
run with: mvn clean javafx:run
The need to execute with IntelliJ is to debug the code"
See:
intellij idea : how to debug a java:fx maven project?
I also think you can just right-click on the maven target for javafx:run and select Debug. I am not sure, I don't make use of the JavaFX maven plugin.
Creating fat jars for JavaFX applications
the fat jar
This is not a recommended configuration, but if you really must do it, you can review:
Maven Shade JavaFX runtime components are missing
That answer doesn't discuss getting such a configuration to work in conjunction with an Idea run/debug configuration, so it may not assist you.
If you do continue with a fat jar, I would not advise using a module-info, as you will be running code off the classpath anyway.
Modular versus non-modular JavaFX applications
If you don't use a fat jar, getting all the module dependencies correct for Spring is tricky anyway because Spring is not currently architected to directly support modules well. Spring 6 will be designed to work well with modules, though I think you should be able to get Spring 5 to work if you try hard enough (I have got it to work in the past for some applications).
Alternately you can just have the JavaFX components as modules and run the rest off the classpath. For example, the "Non-modular with Maven" approach at openjfx.io. Note that in that approach, the JDK and JavaFX modules are still loaded as modules off of the module path, it is only Spring your application that is not providing a module-info.java file and running off the classpath.
Creating runtime images for JavaFX applications
I also advise studying:
these resources for the creation of an appropriate runtime image.

Is it possible to build a java project only once using eclipse and share?

Is it possible to actually build a maven project containing java code to be built once and the binaries can be shared?
Problem: The project I am trying to build would take me about 3-4 hours and requires high internet bandwidth. I am trying to check the possibility of re using this built project among several other machines.
I have worked with c++ projects involving makefiles earlier and this was pretty simpler. I am new to Java / eclipse and would need help to figure out if this is something really possible.
PS:
I did try to find existing solutions; they were not straight forward or they say that this can't be done.
Build once and share it offline
In Maven, you can build your project only once and get a JAR file fully packed with all dependencies. So that, you can share this JAR to other machines off-line.
Below are the steps to make it.
First update your pom.xml with the below setting
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.thanga.MyTest[REPLACE WITH YOUR MAIN CLASS]</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Package your project with the goal package assembly:single as shown below
In console,
mvn package assembly:single
In eclipse,
Run this and you can get the two JAR files. One of them MyFullPack-0.0.1-SNAPSHOT-jar-with-dependencies.jar has the full
dependencies loaded.
You can open the JAR to see the dependencies are packed as shown below.
You can share this JAR to other machines off-line without any more build
Is it possible to actually build a maven project containing java code to be built once and the binaries can be shared?
Yes, that's the whole point of Maven, you build the project once, thus generating an artifact (your jar/war ...) which is stored in your local maven repository.
The following command build the project and save it in the local repo :
mvn clean install
However, if you do this, you only have the artifact on your local repo.
A good practise is to create a repository and store your artifacts over there :
https://maven.apache.org/repository-management.html
The use of the following command would store the snapshot dependency on the repository :
mvn clean deploy
You can then reuse your components through multiples computer by specifying the dependencies in your new project's pom.xml file.
You might want to give a look at this guide :
http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
You would obviously need to configure the repository and your maven project in order to use a setup of this kind.
First things first. Is your project a web application (war) or an enterprise application (ear) or just a stand alone Jar?
you can use the packaging tag in POM.xml to package your application to a JAR,WAR,EAR
Examples:
<packaging>war</packaging>
<packaging>ear</packaging>
<packaging>jar</packaging>
Then run mvn clean install
In project/src/target you should see the jar,war or ear generated which you can use to deploy on your machine or any other machine.
OR
you can also find that in .m2 folder once you have run install.
If you use maven, a mvn install will install your binary into your ${home}/.m2 folder. Those binary will be available for all other maven job that will run on the same machine.
If you need to share your binary between multiple machine, you can deploy your jars to a repository, like nexus or artifactory.
You can just take the jar file of your target folder and copy it to the other machines, otherwise you could use some share repository like nexus oder artifactory to share your built binary. Maven is capable of automatically deploying artifacts into those repositories

Maven Integration Tests With Spring Dependency

I have a project structure where I have the two following (Mavenized) projects:
Database - This project is a Spring project which manages interaction with the webapp's database. It contains code for interacting with the database, as well as many service classes. The Application Context here contains the database connection information, as well as beans for each service class.
WebApp - This project is a JSF project which just contains the UI stuff.
For unit testing the Database project, I have a testing Application Context which communicates with a very simple in-memory database-like structure, so the real database is not modified. The testing portion of this project also contains the structure for the in-memory database.
File Structure:
src/main/java/...
src/main/resources/spring/applicationContext.xml
src/test/java/...
src/test/resources/spring/applicationContext.xml
I want to create automated integration tests for the WebApp project which still uses the in-memory database stuff, as well as the testing Application Context, from the Database project. Unfortunately, Maven doesn't provide the WebApp project with the Database project's test code, so it isn't even accessible.
I tried working around that by using the maven-jar-plugin with the test-jar goal and added the test-jar as a dependency in Eclipse (since I read to do that for this problem), however Eclipse gives me the well known: "Dependency to project database with type test-jar is not fully supported. Classpath and/or deployment issues might arise. Try Maven->Disable Workspace Resolution" message, and doesn't update the dependency code when I make changes to the Database project, which means I have to perform a Maven build every time I make a change in the Database project for the test code in the WebApp project to work with the changes.
Database Project:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
WebApp Project:
<dependency>
<groupId>...</groupId>
<artifactId>database</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
Furthermore, Maven Clean no longer works on the Database project, since it says it cannot delete the test jar. Additionally, the command line doesn't run the tests with Database test jar, so the Maven Install on the WebApp project fails.
What should I do to make this work? I've heard about putting the test code into its own project and using that other project as a test dependency, but that won't work for me because the WebApp project needs to use the Database project's testing Application Context, so the problem is more than just access to the Database project's test code.
If you need the src/test code in your webapp project, just add a dependency with a classifier like this
<dependency>
<groupId>...</groupId>
<artifactId>database</artifactId>
<version>0.0.1-SNAPSHOT</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
Then, you should be able to access everything you need to test the WebApp.

Maven for static web project

I'm trying to add a wst.web facet for a multimodule maven project on eclipse. This wst.web facet is "Static web project"
You would say "why is he using maven for this?"
The point is that the whole project is a tree. I have a parent pom in the root of the project, and it has some modules, and they have their modules too. 3 levels most, for config centralising purposes and plugins and dependencies heritage.
So, one of these modules, contains 2 Static web projects, that are the UI part of other modules that are dynamic. These 2 are meant to be published in an Apache (in a Http Server within eclipse). All this already works with assembly plugin that moves stuff to target and then packs it in a tar.gz... but without the "Static web project" Eclipse does not allow me to publish it to the Http Server. I can do it by hand but that's not the point
My current config to do this is:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectFacets>
<wst.web>1.0</wst.web>
<wst.jsdt.web>1.0</wst.jsdt.web>
</additionalProjectFacets>
</configuration>
</plugin>
This is adding JavaScript 1.0 facet. But not the Static Web Project that I need
Thanks a lot for all your help.
PS: As an another reason to use maven for this, is that this tar.gz produced, is packed in a deb package, that configures the virtual host for apache, with all the AJP proxy needed to work with its backend.

What is the correct maven2 phase for deployment into application server?

I'm trying to configure pom.xml so that it automatically deploys EAR archive to GlassFish application server. I want to attach this operation to the proper maven execution phase. But can't understand which one is dedicated just for this operation? Deploy? Install? Please, help. This is what I'm doing:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>deploy</phase>
<configuration>
<tasks>
<copy file="${project.build.directory}/${project.build.finalName}.ear"
tofile="${glassfish.home}/domains/domain1/autodeploy"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
When I'm doing mvn deploy, maven is trying to deploy my artifacts to repository. This is not what I'm going to accomplish. I feel that the execution phase is wrong..
When I'm doing mvn deploy, maven is trying to deploy my artifacts to repository. This is not what I'm going to accomplish. I feel that the execution phase is wrong...
In the Maven lingua, deploy has nothing to do with the deployment to an application server and is not an appropriate phase to bind a plugin doing this kind of work. Here is what we can read about the deploy phase in the Introduction to the Build Lifecycle:
deploy - done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects.
But, before I go further with phases, I need to mention that there are several plugins allowing to interact with GF (start/stop/deploy/undeploy/etc) that might do a better job than the AntRun plugin (AntRun might work for trivial use cases but, for example, you might want to wait for the deployment to be done and the application to be in a ready state during the build; for such use cases, you need more advanced control). These candidates are:
the Maven Glassfish Plugin: this is a GlassFish specific plugin that can be used with a local or remote GlassFish install.
the Maven Embedded GlassFish Plugin: this is a GlassFish specific plugin that runs an embedded GlassFish. Nice for portable builds.
the Maven Cargo Plugin: this a container agnostic plugin that now supports GlassFish 3.
Using one or the other really depends on your use case. If you don't plan to deploy on many containers, the GlassFish specific plugins are the most powerful. The beauty of Cargo is that it offers an unified API. But its configuration is less intuitive, especially if you're not used to it.
Now, if you just want to deploy an application during development and don't want the build to interact in any way with the container, binding any of these plugins to a particular phase is not that useful, although some people do deploy their app during package.
However, you might want to run integration/functional tests against a container as part of you build. This is actually a perfectly valid and very common use case and the relevant phases to implement this are:
pre-integration-test: perform actions required before integration
tests are executed. This may involve
things such as setting up the required
environment.
integration-test: process and deploy the package if necessary into an
environment where integration tests
can be run.
post-integration-test: perform actions required after integration
tests have been executed. This may
including cleaning up the environment.
The pre-integration-test phase is typically used to start a container and deploy an application on it. The post-integration-test phase is used to undeploy an application and stop the container.
So I think that deploying to a server can be a typical build activity, there are very valid use cases, and this is well supported by Maven. I don't deploy to my development server (nor to production server) as part of a build though.
See also
Maven Embedded Glassfish Plugin
Which Maven Glassfish plugin to use?
In addition to scdef's answer, here's a brief example of what using the cargo plugin looks like: http://blank.jasonwhaley.com/2010/03/automated-deployment-with-cargo-drive.html. I personally didn't bind it to a phase, since I don't want deployment to happen on every invocation of maven and didn't intend on writing another pom/profile to handle invoking the plugin.
Additionally, I'd recommend not using maven at all to deploy my applications to stable environments where there are almost always going to be other applications/databases/systems in the environment that need to be altered in addition placing the application in the container. Production almost always falls under this scope. Coordinating a .war/.ear/whatever deployment to a container/server under this context really should be decoupled from actually building your application. Leave deployments like this to external scripts or perhaps a comprehensive tool like Puppet.
It might not be a direct answer to your question, but have a look at the cargo plugin: http://cargo.codehaus.org/
It addresses this exact need (among other things)
I've implemented that behavior using a copy task with the ant plug-in on maven.
The correct phase for doing this is the package phase.
See http://maven.apache.org/plugins/maven-antrun-plugin/index.html for more details.
Regards.

Categories