Using Gradle serve a front end (JS) and a backend API (Java) - java

Im trying to create a web application using Gradle. The front end UI will be built with Angular.js and the backend should be Java. When I say backend, I mean a Java / Spring based API that will be queried using Ajax from Angular.js.
So basically what Im trying to do is to get any URL's that start with mysite.com/api/... should be routed to the src/com/veight/client files, or in other words to the Java backend. And then any other URLs such as mysite.com/login should be handled by the JavaScript / Angular.js front end.
I have the JavaScript / Angular.js routing working for the front end using the following build.gradle file. How should I go about sending routes that match mysite.com/api/... to the Java / Spring back end?
Thank you for the help!
Note: I know that Java Spring naturally does this routing where it sends certain routes mysite.com/home to one folder and other routes mysite.com/api/... are handled buy a xml file. But I think its possible to handle this in the build.gradle file. So I was hoping to prove / disprove that theory.
File Structure
.gradle
.settings
build
gradle
src
com
veight
client
WebContent
Heres my build.gradle:
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'org.gradle.api.plugins:gradle-tomcat-plugin:1.2.4' // Gradle Tomcat Plugin
classpath 'com.eriwen:gradle-css-plugin:1.11.1'
classpath 'com.eriwen:gradle-js-plugin:1.12.0'
}
}
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'tomcat'
apply plugin: 'eclipse-wtp'
apply plugin: 'js'
apply plugin: 'css'
sourceCompatibility = 1.7
version = '1.0'
task wrapper(type: Wrapper) {
gradleVersion = '2.0'
}
repositories {
mavenCentral() // Allow access to the Maven Centeral Repo
}
dependencies {
def tomcatVersion = '7.0.54'
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
"org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
}
}
sourceSets {
main {
java {
srcDirs 'src'
}
}
}
// End: Java Plugin Configuration
// Start: Tomcat Plugin Configuration
tomcatRun {
httpPort = 8080
stopPort = 8081
URIEncoding = 'utf-8'
webAppSourceDirectory = file('WebContent')
}
eclipse {
wtp {
component {
contextPath = '/'
deployName = 'client'
}
}
}

Related

How to merge client and server builds into one jar with gradle?

I have a project with the following structure:
web-client/ # Angular Client
build/
build.gradle
server/ # Spring Boot Application
build/
build.gradle
build.gradle # The "parent" project. Works on web-client and server
The parent is supposed to copy the compiled web-application into server/build/classes/static such that it will be copied to /BOOT-INF/classes/ of the final jar where it will be served by the Spring Boot server.
Everything is working so far except the last part. Those files are nor copied into the final jar and I think it's because it got already build at the time where the copying task is executed.
This is the script which I am currently using:
task buildWebApp {
outputs.dir('mobile-client/build')
dependsOn ':mobile-client:buildWebApp'
}
task copyWebApp {
doFirst {
copy {
from 'mobile-client/build'
into 'server/build/classes/static'
}
}
dependsOn tasks.buildWebApp
}
# assemble.dependsOn copyWebApp
build.dependsOn copyWebApp
How can I make sure that those files from mobile-client/build end up in the final jar of server?
Cannot guarantee its current functionality, but this I used in one of my projects a few years ago. I did use separate gradle submodule for building Frontend and then separate module for Backend where I included Frontend as a JAR:
root gradle project -> frontend
-> backend
Frontend build.gradle (builds frontend JAR with /static/**)
apply plugin: "com.moowork.node"
apply plugin: 'java'
node {
version = '8.9.3'
download = true
}
def webResources = "$buildDir/web-resources/main"
sourceSets {
main {
output.dir(webResources, builtBy: 'buildWeb')
}
}
task webInstall(type: NpmTask) {
args = ['install']
}
task buildWeb(type: NpmTask) {
dependsOn webInstall
args = ['run', 'build']
}
build.dependsOn buildWeb
Backend build.gradle
apply plugin: 'spring-boot-gradle-plugin'
apply plugin: 'idea'
dependencies {
compile project(':frontend')
}

Gretty, Spring MVC and hot deployment

I am learning Spring MVC and trying to use it together with Gradle and Gretty plugin. I have successfully created a "Hello World" project, however I am not able to use hot deployment with Gretty, despite setting the managedClassReload=true. I run the application by using appRun gretty task from IntelliJ. My build.gradle is as follows:
apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'war'
apply from: 'https://raw.github.com/gretty-gradle-plugin/gretty/master/pluginScripts/gretty.plugin'
group = 'lukeg'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
mainClassName = 'lukeg.LearnApplication'
repositories {
mavenCentral()
maven {
url 'https://repo.spring.io/libs-snapshot'
}
}
dependencies {
compileOnly('org.projectlombok:lombok:+')
compile('org.springframework:spring-webmvc:4.3.17.RELEASE')
compile("org.aspectj:aspectjweaver:1.8.11")
compile('org.springframework:spring-context:4.3.18.BUILD-SNAPSHOT')
providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
}
gretty {
httpPort = 8080
contextPath = '/'
servletContainer = 'tomcat9'
//reloadOnClassChange=true
managedClassReload=true
loggingLevel='DEBUG'
}
It does not matter whether I use tomcat9 or jetty9 for servlet container: the logs do not show that the changes to source files in project are detected by Gretty.
Interesingly enough, when I comment out the managedClassReload=true line and uncomment reloadOnClassChange=true the changes to source files are detected and the project is automatically reloaded.
What can be the cause for gretty's hot deployment not working? Does springloaded not work together with Spring MVC?
First of all, there is no need to depend on the plugin script you are gathering from github since org.gretty is available in the official Gradle plugin repository for some time already:
plugins {
id "org.gretty" version "2.1.0"
}
Since you are running your app inplace using appRun, your changes will not be reloaded.
You have to run you application as war, using appRunWar.
This is not mentioned in the documentation. But in the Gretty source code.
You can check the Gretty code which causing your issue in the BaseScannerManager:
if(wconfig.reloadOnClassChange)
{
if(managedClassReload)
{
if(wconfig.inplace) // <-- your problem, you are running inplace
{
log.info 'file {} is in managed output of {}, servlet-container will not be restarted', f, wconfig.projectPath
}
else
{
log.info 'file {} is in output of {}, but it runs as WAR, servlet-container will be restarted', f, wconfig.projectPath
webAppConfigsToRestart.add(wconfig)
}
}
else
{
log.info 'file {} is in output of {}, servlet-container will be restarted', f, wconfig.projectPath
webAppConfigsToRestart.add(wconfig)
}
}

Include react generated HTML/JS files from composite gradle build

I have 2 Gradle projects that I want to link together. The first project has a standard Spring Boot app, and I want to link it with a ReactJS project that I've added a "build.gradle" file to.
I want to include the files generated into the "build/" directory of the ReactJS project into the "META-INF/resources" directory of the Spring Boot project.
These are my gradle.build files:
Spring Boot Gradle project:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE'
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
group = "com.myproject"
version = "1.0"
bootRun {
systemProperties = System.properties
}
repositories {
jcenter()
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("com.myproject:myproject-ui:1.0")
}
ReactJS Gradle project:
plugins {
id "com.moowork.node" version "1.1.1"
}
node {
download = true
}
apply plugin: 'java'
group = "com.myproject"
version = "1.0"
buildDir = 'dist'
task webjar(type: Jar, dependsOn: 'jar') {
from(fileTree('build')) {
into 'META-INF/resources'
}
}
build.dependsOn(webjar)
build.dependsOn(npm_run_build)
clean {
delete 'dist'
delete 'build'
}
Assume I've setup the "settings.gradle" files correctly such that it is a composite build, because that doesn't seem to cause issues.
When I run the "build" task for the ReactJS project, the "build/" directory is successfully generated, but I doesn't seem to be included by the Spring Boot project anywhere. How can I include the generated HTML/JS files such that they show up when I run the "bootRun" task of the Spring Boot project.
Typically you'd use a Configuration for this
reactjs/build.gradle
configurations {
wj
}
task webjar(type: Jar) { ... }
dependencies {
wj files(webjar)
}
springboot/build.gradle
configurations {
wj
}
dependencies {
wj project(path: ':reactjs', configuration: 'wj')
}
war {
with copySpec {
from zipTree(configurations.wj.singleFile)
into 'META-INF/resources'
}
}

Eclipse WTP + Gradle Buildship not deploying all project dependencies

Config: Eclipse Neon.1. BuildShip plugin 1.0.21. Gradle 3.2. Tomcat 8.0.33.
Project Structure:
CmbProduct
Common
CommonServer
Model
CaBridge
WebApp
I've got a Web Services application project ("WebApp") which is dependent on multiple other projects. When I use Eclipse WST/WTP to deploy and run WebApp via Tomcat, only Model.jar from "Model" is deployed into the tomcat WST runtime directory as:
.metadata/.plugins/org.eclipse.wst.server.core/tmp1/wtpwebapp/WEB-INF/lib/Model.jar
All other dependencies for hibernate, etc do seem to be deployed correctly to the same dir above.
This broke when I changed eclipse to use Buildship. Previously I used the Eclipse STS (Spring) plugin and that worked fine.
Here is the web project (WebApp) build.gradle:
apply plugin: 'war'
apply plugin: 'eclipse-wtp'
dependencies {
compile project(":Common")
compile project(":Model")
compile project(":CommonServer")
compile project(":CaBridge")
...
}
eclipse {
wtp {
component {
// Configure the <Context path="..."/> in server.xml
contextPath = '/console'
// dependencies to mark as deployable with lib folder deploy path
libConfigurations += [ project(":MagniCompCommon").configurations.runtime ]
}
}
}
In the above example I first tried without the eclipse.wtp.libConfigurations section. I tried adding that to fix the problem but it has no effect. Yes, I did run 'gradle eclipseWtp', then Add/Remove the 'WebApp' application from its server entry after making that change.
If I go to Eclipse -> WebApp -> Properties -> Java Build Path -> Libraries and look at "Web App Libraries" I see "Model" but not the other projects. If I look at "Project and External Dependencies" I see all projects listed.
Here is the build.gradle for Model (working):
apply plugin: 'eclipse-wtp'
dependencies {
compile project(":MagniCompCommon")
}
Here is build.gradle for Common (not deployed):
apply plugin: 'eclipse-wtp'
dependencies {
//compile project(":MagniCompCommon")
compile project(":Model")
compile("org.glassfish.jersey.containers:jersey-container-servlet:$jerseyGlassfishVersion")
// Required for JAX-RS Client
compile("org.glassfish.jersey.core:jersey-client:$jerseyGlassfishVersion")
}
Here is build.gradle for the top level project (CmbProject):
apply plugin: 'java'
subprojects {
apply plugin: 'java'
apply plugin: 'nebula.provided-base'
apply plugin: 'nebula.optional-base'
sourceCompatibility = JavaVersion.VERSION_1_8
javadoc.enabled = false
sourceSets {
main {
java {
// Define all source dirs - Purpose is to add "src-gen"
srcDirs = ["src/main/java", "src-gen"]
}
}
}
/*
* Repositories used by each subproject must be given below.
* Because each subproject resolves dependencies of other
* subprojects, all subprojects must know all repos.
* In other words, if projectA needs repo "foo.org" and projectB
* depends upon projectA, then projectB needs repo "foo.org" as
* well.
*/
repositories {
maven {
// Local repo for annovention
url uri("$rootDir/MagniCompCommon/repo")
}
mavenCentral()
maven {
url "http://download.java.net/maven/2"
}
maven {
// Texo/EMF
url "https://oss.sonatype.org/content/groups/public/org/eclipse/emf"
}
maven {
// Eclipse
url "https://oss.sonatype.org/content/repositories/public/eclipse"
}
maven {
url "https://repository.jboss.org/nexus/content/groups/public-jboss"
}
maven {
url "http://maven.vaadin.com/vaadin-addons"
}
maven {
url "http://oss.sonatype.org/content/repositories/vaadin-snapshots"
}
maven {
url("http://maven.clapper.org")
}
/*
* -ADD LAST- so that it doesn' override any others
* DynamicReports depends upon JasperReports which lists their own
* bug fixed versions of packages like "com.lowagie:itext:2.1.7.js2"
* This repo provides such patched packages.
*/
maven {
url("http://jasperreports.sourceforge.net/maven2")
}
}
/*
* Variables local to this file
*/
def bouncycastleVersion = "1.54" // Was 1.51
def slf4jVersion = "1.7.19"
def hibernateVersion = "4.3.11.Final"
def texoVersion = "0.9.0-v201501182340"
def emfVersion = "2.11.0-v20150123-0347"
def jnaVersion = "4.1.0"
ext {
/*
* Variables here are used by subprojects
*/
vaadinVersion = "7.6.8" // was 7.6.4
vaadinIconsVersion = "1.0.1"
jerseyGlassfishVersion = "2.23.2" // was 2.22.2
}
dependencies {
/*
* PRODUCT SPECIFIC
*/
compile("org.bouncycastle:bcprov-jdk15on:$bouncycastleVersion")
compile("org.bouncycastle:bcprov-ext-jdk15on:$bouncycastleVersion")
compile("org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion")
compile("com.h2database:h2:1.3.176")
testCompile("org.testng:testng:6.9.4")
/*
* MagniComp common and product
*/
compile("org.simpleframework:simple-xml:2.6.9")
// Logging slf4j API
compile("org.slf4j:slf4j-api:$slf4jVersion")
// Send JCL to slf4j
compile("org.slf4j:jcl-over-slf4j:$slf4jVersion")
// Anything using JUL should defer to slf4j
compile("org.slf4j:jul-to-slf4j:$slf4jVersion")
// Send slf4j to log4j 1.2 for those JARs which use slf4j
compile("org.slf4j:slf4j-log4j12:$slf4jVersion")
// Log4j itself
compile("log4j:log4j:1.2.17")
// Hibernate
// Do not include "hibernate-core" explicitly as hibernate-entitymanager will take care of it
compile("org.hibernate:hibernate-entitymanager:$hibernateVersion")
compile("org.hibernate:hibernate-c3p0:$hibernateVersion")
compile("mysql:mysql-connector-java:5.1.38")
// Texo
compile("org.eclipse.emf:org.eclipse.emf.texo:$texoVersion")
compile("org.eclipse.emf:org.eclipse.emf.texo.server:$texoVersion")
compile("org.eclipse.emf:org.eclipse.emf.texo.xml:$texoVersion")
// Texo dependencies (not automaticly added by texo)
compile("org.eclipse.emf:org.eclipse.emf.common:$emfVersion")
compile("org.eclipse.emf:org.eclipse.emf.ecore:$emfVersion")
compile("org.eclipse.emf:org.eclipse.emf.ecore.xmi:$emfVersion")
// Required by org.eclipse.emf
// Disable because it's causing:
// java.lang.SecurityException: class "org.osgi.framework.BundleReference"'s signer information does not match signer information of other classes in the same package
//compile("org.eclipse.core:org.eclipse.core.runtime:3.7.0")
compile("org.jsoup:jsoup:1.7.2")
// Apache HTTP client
compile("org.apache.httpcomponents:httpclient:4.3.5")
// EventBus and more
compile("com.google.guava:guava:18.0")
// Quartz scheduler
compile("org.quartz-scheduler:quartz:2.2.2") {
exclude group: "c3p0", module: "c3p0"
}
// Java Mail
compile("javax.mail:mail:1.4.5")
// JNA for Common and CaBridge
compile("net.java.dev.jna:jna:$jnaVersion")
compile("net.java.dev.jna:jna-platform:$jnaVersion")
// This package provided by Tomcat or Servlet container
provided("javax.servlet:javax.servlet-api:3.1.0")
}
}
Thanks to some help from the gradle forum I found the solution.
Each project which is a dependency of a WTP project must each have:
apply plugin: 'eclipse-wtp'
Having this only in the WTP project is not enough.

Gradle all in one build

I would like to use Gradle to build a java project and I would like to structure it as follows.
Core Library
Web App (war plugin)
Server (application plugin)
Client
Client War (war plugin)
The Web App, Server, and Client all depend on core. The Server depends on the Web App because it is going to serve it as the admin page using embedded Jetty. The Client War depends on the Client. The Client War is to be deployed to a web server for distribution of the client as a web start application.
What I would like to know is how can I tell the Server project that it depends on the Web App and needs to copy it into the proper location in it's distribution structure. I would also like to know how I can tell the Client War project to depend on the Client project and to copy the Client jar and all of it's dependencies into the proper location to build the war archive.
I plan to use the application plugin for the Server so under <root>/src/dist there will be a webapp directory where the one or possibly more web apps will reside. It is expected that the files contained in the webapp directory will be war files.
This is a new project so it can follow the standard build conventions of Gradle and the project layout expected by Gradle.
Ideally at some point the Client artifacts will be published to an internal Artifactory or Sonatype Nexus repository so that the Client War can be built with version support.
So far I have found the following resources.
Packaging JNLP Applications in a Web Archive
Generating Java Web Start files using Gradle
I believe I figured out the Web App dependency part of my problem. The Client War is a lost cause for now.
Server build.gradle
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'application'
targetCompatibility = 1.8
sourceCompatibility = 1.8
version = '0.0.1-SNAPSHOT'
group = 'com.s2d'
mainClassName = 'com.simonsoftwaredesign.example.echo.server.EchoServerApp'
repositories {
mavenCentral()
}
configurations {
webContainer
}
dependencies {
compile project(':echo-core')
compile group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.3.7.v20160115'
compile group: 'org.eclipse.jetty', name: 'jetty-webapp', version: '9.3.7.v20160115'
webContainer project(path: ':echo-admin', configuration: 'warApp')
}
task copyWebApps(dependsOn: configurations.webContainer, type: Copy) {
from { configurations.webContainer.collect { it } }
// I don't like how this is hard coded
// but I am not sure how to fix it
into 'src/main/dist/webapp'
}
installDist.dependsOn copyWebApps
distZip.dependsOn copyWebApps
distTar.dependsOn copyWebApps
Web App build.gradle
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'war'
targetCompatibility = 1.8
sourceCompatibility = 1.8
version = '0.0.1-SNAPSHOT'
group = 'com.s2d'
configurations {
warApp
}
repositories {
mavenCentral()
}
dependencies {
providedCompile project(':echo-core')
providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
}
artifacts {
warApp war
}
Gradle projects depending on artifacts created by sibling projects

Categories

Resources