I know that it is possible to include AngularJs with Maven into a Spring project for instance but how would one include it with Gradle?
Looking into gradle repositor
I have AngularJS 2 + Spring Boot application with Gradle. I use typescript (.ts file) and npm (node js package manager). So I'm running npm install for generate node_modules and npm run tsc for translating typescript to javascript. I still use some of webjars though, basically dependencies are gathered by npm task during build time and wired by systemjs.config.js file
Below is my folder structure
/src/main/java
/src/main/resources
/app - .ts files and .js translated from .ts
/css
/js - systemjs.config.js
/node_modules - generated by npm install
/typings - generated by npm install
package.json
tsconfig.json
typings.json
/src/main/webapp/WEB-INF/jsp - .jsp files
This is my build.gradle file and add two custom tasks (npmInstall and npmRunTsc) to run npm tasks
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.5.RELEASE")
classpath("org.flywaydb:flyway-gradle-plugin:3.2.1")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'war'
war {
baseName = 'my-angular-app'
version = '1.0'
manifest {
attributes 'Main-Class': 'com.my.Application'
}
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenLocal()
mavenCentral()
}
task npmInstall(type:Exec) {
workingDir 'src/main/resources'
commandLine 'npm', 'install'
standardOutput = new ByteArrayOutputStream()
ext.output = {
return standardOutput.toString()
}
}
task npmRunTsc(type:Exec) {
workingDir 'src/main/resources'
commandLine 'npm', 'run', 'tsc'
standardOutput = new ByteArrayOutputStream()
ext.output = {
return standardOutput.toString()
}
}
dependencies {
// tag::jetty[]
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-tomcat",
"org.springframework.boot:spring-boot-starter-data-jpa",
"org.springframework.boot:spring-boot-starter-actuator",
"org.springframework.boot:spring-boot-starter-security",
"org.springframework.boot:spring-boot-starter-batch",
"org.springframework.cloud:spring-cloud-starter-config:1.0.3.RELEASE",
"org.springframework.cloud:spring-cloud-config-client:1.0.3.RELEASE",
"com.google.code.gson:gson",
"commons-lang:commons-lang:2.6",
"commons-collections:commons-collections",
"commons-codec:commons-codec:1.10",
"commons-io:commons-io:2.4",
"com.h2database:h2",
"org.hibernate:hibernate-core",
"org.hibernate:hibernate-entitymanager",
"org.webjars:datatables:1.10.5",
"org.webjars:datatables-plugins:ca6ec50",
"javax.servlet:jstl",
"org.apache.tomcat.embed:tomcat-embed-jasper",
"org.quartz-scheduler:quartz:2.2.1",
"org.jolokia:jolokia-core",
"org.aspectj:aspectjweaver",
"org.perf4j:perf4j:0.9.16",
"commons-jexl:commons-jexl:1.1",
"cglib:cglib:3.2.1",
"org.flywaydb:flyway-core",
)
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
testCompile("junit:junit",
"org.springframework:spring-test",
"org.springframework.boot:spring-boot-starter-test",
"org.powermock:powermock-api-mockito:1.6.2",
"org.powermock:powermock-module-junit4:1.6.2",
)
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
When I run the gradle build process I run like below
$ gradle clean npmInstall npmRunTsc test bootRepackage
I can use same systemjs.config.js shown on AngularJS tutorial
systemjs.config.js
(function(global) {
// map tells the System loader where to look for things
var map = {
'app': 'app', // 'dist',
'rxjs': 'node_modules/rxjs',
'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
'@angular': 'node_modules/@angular'
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'main.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'angular2-in-memory-web-api': { defaultExtension: 'js' },
};
var packageNames = [
'@angular/common',
'@angular/compiler',
'@angular/core',
'@angular/http',
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/router',
'@angular/router-deprecated',
'@angular/testing',
'@angular/upgrade',
];
// add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' }
packageNames.forEach(function(pkgName) {
packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});
var config = {
map: map,
packages: packages
}
System.config(config);
})(this);
And on .jsp file I include the systemjs.config.js in head section
<script type="text/javascript" src="node_modules/zone.js/dist/zone.js"></script>
<script type="text/javascript" src="node_modules/reflect-metadata/Reflect.js"></script>
<script type="text/javascript" src="node_modules/systemjs/dist/system.src.js"></script>
<script type="text/javascript" src="js/systemjs.config.js"></script>
For last, to sort out context path I do like below on my Spring WebMvcConfigurerAdapter
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.my.controller")
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/webjars/**")) {
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
if (!registry.hasMappingForPattern("/images/**")) {
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/");
}
if (!registry.hasMappingForPattern("/css/**")) {
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/css/");
}
if (!registry.hasMappingForPattern("/js/**")) {
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/js/");
}
if (!registry.hasMappingForPattern("/app/**")) {
registry.addResourceHandler("/app/**").addResourceLocations("classpath:/app/");
}
if (!registry.hasMappingForPattern("/node_modules/**")) {
registry.addResourceHandler("/node_modules/**").addResourceLocations("classpath:/node_modules/");
}
}
@Bean
public InternalResourceViewResolver internalViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
viewResolver.setOrder(1);
return viewResolver;
}
}
Although it turned out in the discussion below the question that it doesn't make sense to download angular via gradle it can be done with the following piece of code:
repositories {
ivy {
name = 'AngularJS'
url = 'https://code.angularjs.org/'
layout 'pattern', {
artifact '[revision]/[module](.[classifier]).[ext]'
}
}
}
configurations {
angular
}
dependencies {
angular group: 'angular', name: 'angular', version: '1.3.9', classifier: 'min', ext: 'js'
}
task fetch(type: Copy) {
from configurations.angular
into 'src/main/webapp/js'
rename {
'angular.js'
}
}
Check out webjars, i highly recommend it.
I've just used it in Maven and Gradle project.
Basically it is just what we needed, a vast collection of front-end projects and frameworks packaged in jars.
Add this dependency to your build.gradle
script:
compile 'org.webjars:angularjs:1.3.14'
Go to documentation section for a quick setup guide for Spring
include angular.js
or some other module from the jar in you script like a local resource
<script src="where-you-exposed-webjars/angular/1.3.14/angular.js"></script>
require.js
scriptIt may be late, but checkout https://github.com/gharia/spring-boot-angular. This is Spring Boot project with angular JS using asset-pipeline.
EDIT:
Using this gradle plugin, we can easily manage the client side dependencies, either of npm or bower or GIT. Please see the sample build.gradle below, in which I have included several dependencies of Angular in clientDependencies
.
buildscript {
repositories {
mavenCentral()
mavenLocal()
maven { url "https://repo.grails.org/grails/core" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.3.RELEASE")
classpath("org.codehaus.groovy:groovy:2.4.6")
classpath("gradle.plugin.com.boxfuse.client:flyway-release:4.0")
}
}
plugins {
id 'com.craigburke.client-dependencies' version '1.0.0-RC2'
}
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'war'
jar {
baseName = 'boot-demo'
version = '0.1.0'
}
repositories {
mavenCentral()
mavenLocal()
maven { url "https://repo.grails.org/grails/core" }
jcenter()
maven { url "http://repo.spring.io/libs-snapshot" }
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
configurations {
providedRuntime
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
compile("org.springframework.boot:spring-boot-starter-actuator")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("org.codehaus.groovy:groovy")
testCompile("org.springframework.boot:spring-boot-starter-test")
testCompile("junit:junit")
}
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}
clientDependencies {
npm {
'angular'('1.5.x', into: 'angular') {
include 'angular.js'
include 'angular.min.js'
}
'angular-resource'('1.5.x', into: 'angular') {
include 'angular-resource.js'
include 'angular-resource.min.js'
}
'angular-mocks'('1.5.x', into: 'angular') {
include 'angular-mocks.js'
include 'angular-mocks.min.js'
}
'angular-route'('1.5.x', into: 'angular'){
include 'angular-route.js'
include 'angular-route.min.js'
}
'angular-animate'('1.5.x', into: 'angular') {
include 'angular-animate.js'
include 'angular-animate.min.js'
}
}
}
assets {
minifyJs = true
minifyCss = true
}
Please see the following blog for details of architecture of sample Spring Boot Project with angular.:
https://ghariaonline.wordpress.com/2016/04/19/spring-boot-with-angular-using-gradle/