blob: e8c4fdadc669b8a4c2021538c4e8a2346c005ceb [file] [log] [blame]
<?php
/*******************************************************************************
* Copyright (c) 2015, 2016 Eclipse Foundation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eric Poirier (Eclipse Foundation) - Initial implementation
* Christopher Guindon (Eclipse Foundation)
*******************************************************************************/
// This file must be included
if(basename(__FILE__) == basename($_SERVER['PHP_SELF'])){exit();}
?>
<h1 class="article-title"><?php echo $pageTitle; ?></h1>
<p>This article shows you how to build a simple blog application with <a target="_blank" href="https://jhipster.github.io/">JHipster</a> 4. At the time of this writing (January 10, 2017), JHipster 4 has not been released.</p>
<p><b>Source Code</b><br>
If you'd like to get right to it, the <a target="_blank" href="https://github.com/mraible/jhipster4-demo">source for this application is on GitHub</a>. To run the app, use <code>./mvnw</code>. To test it, run <code>./mvnw test</code>. To run its integration tests, run <code>./mvnw</code> in one terminal and <code>yarn run e2e</code> in another.</p>
<h2>What is JHipster?</h2>
<p>JHipster is one of those open-source projects you stumble upon and immediately think, "Of course!" It combines three very successful frameworks in web development: Bootstrap, Angular, and Spring Boot. Bootstrap was one of the first dominant web-component frameworks. Its largest appeal was that it only required a bit of HTML and it worked! All the efforts we made in the Java community to develop web components were shown a better path by Bootstrap. It leveled the playing field in HTML/CSS development, much like Apple's Human Interface Guidelines did for iOS apps.</p>
<p>JHipster was started by Julien Dubois in October 2013 (Julien's first commit was on <a target="_blank" href="https://github.com/jhipster/generator-jhipster/commit/c8630ab7af7b6a99db880b3b0e2403806b7d2436">October 21, 2013</a>). The first public release (version 0.3.1) was launched December 7, 2013. Since then, the project has had over 115 releases! It is an open-source, Apache 2.0-licensed project on GitHub. It has a core team of 16 developers and over 280 contributors. You can find its homepage at <a target="_blank" href="http://jhipster.github.io/">http://jhipster.github.io</a>. If you look at <a target="_blank" href="https://github.com/jhipster/generator-jhipster">the project on GitHub</a>, you can see it's mostly written in JavaScript (42%) and Java (27%).</p>
<p>At its core, JHipster is a <a target="_blank" href="http://yeoman.io/">Yeoman</a> generator. Yeoman is a code generator that you run with a <code>yo</code> command to generate complete applications or useful pieces of an application. Yeoman generators promote what the Yeoman team calls the "Yeoman workflow". This is an opinionated client-side stack of tools that can help developers quickly build beautiful web applications. It takes care of providing everything needed to get working without the normal pains associated with a manual setup.</p>
<p>JHipster 4 is the same JHipster many developers know and love, with a couple bright and shiny new features: namely Angular and Bootstrap 4 support.</p>
<p><b>NOTE</b>: When I say "AngularJS", I mean Angular 1.x. "Angular" is the forward-looking name for Angular 2 and beyond.</p>
<h2>Install JHipster 4</h2>
<p>The <a target="_blank" href="http://jhipster.github.io/installation/">Installing JHipster</a> instructions show you all the tools you'll need to use a released version of JHipster. These instructions have not been updated for JHipster 4, so here's the abbreviated version.</p>
<ol>
<li>Install Java 8 <a target="_blank" href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">from Oracle</a>.</li>
<li>Install Git from <a target="_blank" href="https://git-scm.com">https://git-scm.com</a>.</li>
<li>Install Node.js from <a target="_blank" href="http://nodejs.org">http://nodejs.org</a>. I used Node 6.9.1 to write this article.</li>
<li>Install Yarn using the <a target="_blank" href="https://yarnpkg.com/en/docs/install">Yarn installation instructions</a>.</li>
<li>Run the following command to install <a target="_blank" href="http://yeoman.io/">Yeoman</a>.</li>
</ol>
<pre>
yarn global add yo</pre>
<p>Since JHipster 4 is not released yet, you'll need to clone its GitHub repository to create a project with it.</p>
<pre>git clone https://github.com/jhipster/generator-jhipster</pre>
<p>After cloning it locally, you'll need to run <code>npm link</code> in the <code>generator-jhipster</code> directory so npm knows to use your local copy instead of trying to download and install it.</p>
<h2>Create a Project</h2>
<p>To create a project, open a terminal window and create a directory. For example, <code>mdkdir blog</code>. Navigate into the directory and run <code>yo jhipster</code>. You'll be asked a number of questions about the type of application you want to create and what features you'd like to include. The screenshot below shows the choices I made to create a simple blog application with Angular.</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/generating-blog.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/generating-blog_sm.png" alt="Generating the application"/></a></p>
<p align="center">Figure 1. Generating the application</p>
<p>If you'd like to create the same application I did, you can place the following <code>.yo-rc.json</code> file in an empty directory and run <code>yo jhipster</code> in it. You won't be prompted to answer any questions because the answers are already in <code>.yo-rc.json</code>.</p>
<pre>
{
"generator-jhipster": {
"jhipsterVersion": "3.12.2",
"baseName": "blog",
"packageName": "org.jhipster",
"packageFolder": "org/jhipster",
"serverPort": "8080",
"authenticationType": "jwt",
"hibernateCache": "ehcache",
"clusteredHttpSession": false,
"websocket": false,
"databaseType": "sql",
"devDatabaseType": "h2Disk",
"prodDatabaseType": "postgresql",
"searchEngine": false,
"messageBroker": false,
"buildTool": "maven",
"enableSocialSignIn": false,
"jwtSecretKey": "fac063fc9ee4dade2472173f04f4d19c4c434aba",
"useSass": true,
"clientPackageManager": "yarn",
"applicationType": "monolith",
"clientFramework": "angular2",
"testFrameworks": [
"gatling",
"protractor"
],
"jhiPrefix": "jhi",
"enableTranslation": true,
"nativeLanguage": "en",
"languages": [
"en",
"es"
]
}
}
</pre>
<p>The project creation process will take a couple minutes to run, depending on your internet connection speed. When it's finished, you should see output like the following.</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/generation-success.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/generation-success_sm.png" alt="Generation success"/></a></p>
<p align="center">Figure 2. Generation success</p>
<p>Run <code>/.mvnw</code> to start the application and navigate to <a target="_blank" href="http://localhost:8080">http://localhost:8080</a> in your favorite browser. The first thing you'll notice is a dapper-looking fellow explaining how you can sign in or register.</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/default-homepage.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/default-homepage_sm.png" alt="Default homepage"/></a></p>
<p align="center">Figure 3. Default homepage</p>
<p>Sign in with username <code>admin</code> and password <code>admin</code> and you'll have access to navigate through the Administration section. This section offers nice looking UIs on top of some Spring Boot's many monitoring and configuration features. It also allows you to administer users:</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/user-management.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/user-management_sm.png" alt="User management"/></a></p>
<p align="center">Figure 4. User management</p>
<p>It gives you insights into Application and JVM metrics:</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/app-metrics.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/app-metrics_sm.png" alt="Application metrics"/></a></p>
<p align="center">Figure 5. Application metrics</p>
<p>And it allows you to see the Swagger docs associated with its API.</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/swagger-docs.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/swagger-docs_sm.png" alt="Swagger docs"/></a></p>
<p align="center">Figure 6. Swagger docs</p>
<p>You can run the following command (in a separate terminal window) to run the Protractor tests and confirm everything is working properly.</p>
<pre>yarn run e2e</pre>
<p>At this point, it's a good idea to check your project into Git so you can easily see what changes are made going forward.</p>
<pre>git init
git add .
git commit -m "Project created"
</pre>
<h2>Generate Entities</h2>
<p>For each entity you want to create, you will need:</p>
<ul>
<li>a database table;</li>
<li>a Liquibase change set;</li>
<li>a JPA entity class;</li>
<li>a Spring Data <code>JpaRepository</code> interface;</li>
<li>a Spring MVC <code>RestController</code> class;</li>
<li>an Angular model, state, component, dialog components, service; and</li>
<li>several HTML pages for each component.</li>
</ul>
<p>In addition, you should have integration tests to verify that everything works and performance tests to verify that it runs fast. In an ideal world, you'd also have unit tests and integration tests for your Angular code.</p>
<p>The good news is JHipster can generate all of this code for you, including integration tests and performance tests. In addition, if you have entities with relationships, it will generate the necessary schema to support them (with foreign keys), and the TypeScript and HTML code to manage them. You can also set up validation to require certain fields as well as control their length.</p>
<p>JHipster supports several methods of code generation. The first uses its <a target="_blank" href="https://jhipster.github.io/creating-an-entity/">entity sub-generator</a>. The entity sub-generator is a command-line tool that prompts you with questions which you answer. <a target="_blank" href="https://jhipster.github.io/jdl-studio/">JDL-Studio</a> is a browser-based tool for defining your domain model with JHipster Domain Language (JDL). Finally, <a target="_blank" href="https://jhipster.github.io/jhipster-uml/">JHipster-UML</a> is an option for those that like UML. Supported UML editors include <a target="_blank" href="https://www.modeliosoft.com/">Modelio</a>, <a target="_blank" href="http://www.umldesigner.org/">UML Designer</a>, <a target="_blank" href="https://www.genmymodel.com/">GenMyModel</a> and <a target="_blank" href="http://www.visual-paradigm.com/">Visual Paradigm</a>. I like the visual nature of JDL-Studio, so I'll use it for this project.</p>
<p>Below is the entity diagram and JDL code needed to generate a simple blog with blogs, entries and tags.</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/jdl-studio.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/jdl-studio_sm.png" alt="Blog entity diagram"/></a></p>
<p align="center">Figure 7. Blog entity diagram</p>
<p>You can <a href="http://bit.ly/jhipster-blog-jdl">click on this URL</a>, or copy/paste the contents of the file below to your hard drive if you'd like to follow along.</p>
<p style="color:#7a2518"><i>.jhipster-jdl.jh</i></p>
<pre>
entity Blog {
name String required minlength(3),
handle String required minlength(2)
}
entity Entry {
title String required,
content String required,
date ZonedDateTime required
}
entity Tag {
name String required minlength(2)
}
relationship ManyToOne {
Blog{user(login)} to User
}
relationship ManyToOne {
Entry{blog(name)} to Blog
}
relationship ManyToMany {
Entry{tag(name)} to Tag{entry}
}
paginate Entry, Tag with infinite-scroll
</pre>
<p>In order to use the JHipster 4 entity generator, you <b>must run the following command</b> within your project. If you don't, the JHipster 3.x entity generator will be used and you'll end up with a bunch of AngularJS code in your project.</p>
<pre>
npm link generator-jhipster
</pre>
<p>Run the following command (in the <code>blog</code> directory) to import this file and generate entities, tests and a UI.</p>
<pre>
yo jhipster:import-jdl ~/Downloads/jhipster-jdl.jh
</pre>
<p>You'll be prompted to overwrite <code>src/main/resources/config/liquibase/master.xml</code>. Type <code>a</code> to overwrite this file, as well as others. At the end, you might see the following output, which you can ignore. The entity sub-generator for JHipster 4 is still a work-in-progress.</p>
<pre>
[10:26:44] Local gulp not found in ~/dev/blog
[10:26:44] Try running: npm install gulp
</pre>
Start the application with <code>/.mvnw</code> and you should be able to view the UI for the generated entities. Create a couple blogs for the existing <code>admin</code> and <code>user</code> users, as well as a few blog entries.
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/blogs.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/blogs_sm.png" alt="Blogs"/></a></p>
<p align="center">Figure 8. Blogs</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/entries.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/entries_sm.png" alt="Entries"/></a></p>
<p align="center">Figure 9. Entries</p>
<p>From these screenshots, you can see that users can see each other's data, and modify it.</p>
<h2>Add Business Logic</h2>
<p><b>TIP</b>: To configure Eclipse with your JHipster project, see <a target="_blank" href="https://jhipster.github.io/configuring-ide-eclipse/">Configuring Eclipse with Maven</a>.</p>
<p>To add more security around blogs and entries, open <code>BlogResource.java</code> and find the <code>getAllBlogs()</code> method. Change the following line:</p>
<p style="color:#7a2518"><i>src/main/java/org/jhipster/web/rest/BlogResource.java</i></p>
<pre>
List&lt;Blog&gt; blogs = blogRepository.findAll();</pre>
<p>To:</p>
<p style="color:#7a2518"><i>src/main/java/org/jhipster/web/rest/BlogResource.java</i></p>
<pre>
List&lt;Blog&gt; blogs = blogRepository.findByUserIsCurrentUser();
</pre>
<p>The <code>findByUserIsCurrentUser()</code> method is generated by JHipster in the <code>BlogRespository</code> class and allows limiting results by the current user.</p>
<p style="color:#7a2518"><i>src/main/java/org/jhipster/repository/BlogRepository.java</i></p>
<pre>public interface BlogRepository extends JpaRepository&lt;Blog,Long&gt; {
@Query("select blog from Blog blog where blog.user.login = ?#{principal.username}")
List&lt;Blog&gt; findByUserIsCurrentUser();
}
</pre>
<p>After making this change, re-compiling <code>BlogResource</code> should trigger a restart of the application thanks to <a target="_blank" href="http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html">Spring Boot's Developer tools</a>. If you navigate to <a target="_blank" href="">http://localhost:8080/blogs</a>, you should only see the blog for the current user.</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/blogs-admin.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/blogs-admin_sm.png" alt="Admin's blog"/></a></p>
<p align="center">Figure 10. Admin's blog</p>
<p>To add this same logic for entries, open <code>EntryResource.java</code> and find the <code>getAllEntries()</code> method. Change the following line:</p>
<p style="color:#7a2518"><i>src/main/java/org/jhipster/web/rest/EntryResource.java</i></p>
<pre>Page&lt;Entry&gt; page = entryRepository.findAll(pageable);</pre>
<p>To:</p>
<p style="color:#7a2518"><i>src/main/java/org/jhipster/web/rest/EntryResource.java</i></p>
<pre>Page&lt;Entry&gt; page = entryRepository.findByBlogUserLoginOrderByDateDesc(SecurityUtils.getCurrentUserLogin(), pageable);</pre>
<p>Using your IDE, create this method in the <code>EntryRepository</code> class. It should look as follows:</p>
<p style="color:#7a2518"><i>src/main/java/org/jhipster/repository/EntryRepository.java</i></p>
<pre>Page&lt;Entry&gt; findByBlogUserLoginOrderByDateDesc(String currentUserLogin, Pageable pageable);</pre>
<p>Recompile both changed classes and verify that the <code>user</code> user only sees the entries you created for them.</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/entries-user.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/entries-user_sm.png" alt="User's entries"/></a></p>
<p align="center">Figure 11. User's entries</p>
<p>After making this changes, commit them to Git.</p>
<pre>git add .
git commit -m "Add business logic"</pre>
<p>You might notice that this application doesn't look like a blog and it doesn't allow HTML in the content field.</p>
<h2>Make UI Enhancements</h2>
<p>When doing UI development on a JHipster-generated application, it's nice to see your changes as soon as you save a file. JHipster 4 uses <a target="_blank" href="https://www.browsersync.io/">Browsersync</a> and <a target="_blank" href="https://webpack.github.io/">webpack</a> to power this feature. To enable it, run the following command in the <code>blog</code> directory.</p>
<pre>npm start</pre>
<p>Running this command will open your default browser and navigate to <a target="_blank" href="http://localhost:9000">http://localhost:9000</a>.</p>
<p>In this section, you'll change the following:</p>
<ol>
<li>Change the content field in an entry from <code>&lt;input&gt;</code> to a <code>&lt;textarea&gt;</code></li>
<li>Change the rendered content field to display HTML</li>
<li>Change the list of entries to look like a blog</li>
</ol>
<h3>Content as textarea</h3>
<p>Open <code>entry-dialog.component.html</code> and change the <code>&lt;input&gt;</code> field for <code>content</code> to a <code>&lt;textarea&gt;</code>. After making this change, it should look as follows:</p>
<p style="color:#7a2518"><i>src/main/webapp/app/entities/entry/entry-dialog.component.html</i></p>
<pre>&lt;textarea class="form-control" name="content" id="field_content" [(ngModel)]="entry.content"
rows="5" required&gt;&lt;textarea&gt;
</pre>
<h3>Allow HTML</h3>
<p>If you enter HTML in this field, you'll notice it's escaped on the list screen.</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/entries-with-html-escaped.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/entries-with-html-escaped_sm.png" alt="Escaped HTML"/></a></p>
<p align="center">Figure 12. Escaped HTML</p>
<p>To change this behavior, open <code>entry.component.html</code> and change the following line:</p>
<p style="color:#7a2518"><i>src/main/webapp/app/entities/entry/entry.component.html</i></p>
<pre>&lt;td&gt;{{entry.content}}&lt;/td&gt;</pre>
<p>To:</p>
<p style="color:#7a2518"><i>src/main/webapp/app/entities/entry/entry.component.html</i></p>
<pre>&lt;td [innerHTML]="entry.content"&gt;&lt;/td&gt;
</pre>
<p>After making this change, you'll see that the HTML is no longer escaped.</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/entries-with-html.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/entries-with-html_sm.png" alt="HTML in entries"/></a></p>
<p align="center">Figure 13. HTML in entries</p>
<h3>Improve the layout</h3>
<p>To make the list of entries look like a blog, replace <code>&lt;div class="table-responsive"&gt;</code> and its inner <code>&lt;table&gt;</code> with HTML so it uses stacked layout in a single column.
<p style="color:#7a2518"><i>src/main/webapp/app/entities/entry/entry.component.html</i></p>
<pre>
&lt;div infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0"&gt;
&lt;div *ngFor="let entry of entries; trackBy trackId"&gt;
&lt;h2&gt;{{entry.title}}&lt;/h2&gt;
&lt;small&gt;Posted on {{entry.date | date: 'short'}} by {{entry.blog.user.login}}&lt;/small&gt;
&lt;div [innerHTML]="entry.content"&gt;&lt;/div&gt;
&lt;div class="btn-group mb-2 mt-1"&gt;
&lt;button type="submit"
uiSref="entry.edit" [uiParams]="{ id: entry.id }"
class="btn btn-sm btn-primary"&gt;
&lt;span class="glyphicon glyphicon-pencil"&gt;&lt;/span&gt;&nbsp;&lt;span
translate="entity.action.edit"&gt; Edit&lt;/span&gt;
&lt;/button&gt;
&lt;button type="submit"
uiSref="entry.delete"
[uiParams]="{ id: entry.id }"
class="btn btn-sm btn-danger"&gt;
&lt;span class="glyphicon glyphicon-remove-circle"&gt;&lt;/span&gt;&nbsp;&lt;span translate="entity.action.delete"&gt; Delete&lt;/span&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>Now it looks more like a regular blog!</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/blog-entries.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/blog-entries_sm.png" alt="Blog entries"/></a></p>
<p align="center">Figure 14. Blog entries</p>
<h2>Deploy to the Cloud</h2>
<p>A JHipster application can be deployed anywhere a Spring Boot application can be deployed.</p>
<p>JHipster ships with support for deploying to <a target="_blank" href="https://jhipster.github.io/cloudfoundry/">Cloud Foundry</a>, <a target="_blank" href="https://jhipster.github.io/heroku/">Heroku</a>, <a target="_blank" href="https://jhipster.github.io/kubernetes/">Kubernetes</a>, <a target="_blank" href="https://jhipster.github.io/aws/">AWS</a>, and <a target="_blank" href="https://jhipster.github.io/boxfuse/">AWS with Boxfuse</a>. I'm using Heroku in this example because it doesn't cost me anything to host it.</p>
<p>When you prepare a JHipster application for production, it's recommended to use the pre-configured "production" profile. With Maven, you can package your application by specifying the <code>prod</code> profile when building.</p>
<pre>mvn -Pprod package</pre>
<p>The production profile is used to build an optimized JavaScript client. You can invoke this using webpack by running <code>yarn run webpack:prod</code>. The production profile also configures gzip compression with a servlet filter, cache headers, and monitoring via
<a target="_blank" href="https://github.com/dropwizard/metrics">Metrics</a>. If you have a <a target="_blank" href="http://graphite.wikidot.com/">Graphite</a> server configured in your <code>application-prod.yaml</code> file, your application will automatically send metrics data to it.</p>
<p>To upload this blog application, I logged in to my Heroku account using <code>heroku login</code> from the command line. I already had the <a target="_blank" href="https://devcenter.heroku.com/articles/heroku-command-line">Heroku CLI</a> installed.</p>
<pre>$ heroku login
Enter your Heroku credentials.
Email: matt@raibledesigns.com
Password (typing will be hidden):
Logged in as matt@raibledesigns.com
</pre>
<p>I ran <code>yo jhipster:heroku</code> as recommended in the <a target="_blank" href="http://jhipster.github.io/heroku/">Deploying to Heroku</a> documentation. I used the name "jhipster4-demo" for my application when prompted.</p>
<pre>
$ yo jhipster:heroku
Heroku configuration is starting
? Name to deploy as: jhipster4-demo
? On which region do you want to deploy ? us
Using existing Git repository
Installing Heroku CLI deployment plugin
Creating Heroku application and setting up node environment
heroku create jhipster-4-demo
https://jhipster-4-demo.herokuapp.com/ | https://git.heroku.com/jhipster-4-demo.git
Provisioning addons
Created heroku-postgresql --as DATABASE
Creating Heroku deployment files
create src/main/resources/config/bootstrap-heroku.yml
create src/main/resources/config/application-heroku.yml
create Procfile
Building application
...
remote: https://jhipster-4-demo.herokuapp.com/ deployed to Heroku
remote:
-----> Done
Your app should now be live. To view it run
heroku open
And you can view the logs with this command
heroku logs --tail
After application modification, redeploy it with
yo jhipster:heroku
</pre>
<p>I ran <code>heroku open</code>, logged as <code>admin</code> and was pleased to see it worked!</p>
<p align="center"><a target="_blank" href="/community/eclipse_newsletter/2017/january/images/jhipster4-demo-heroku.png"><img class="img-responsive" src="/community/eclipse_newsletter/2017/january/images/jhipster4-demo-heroku_sm.png" alt="JHipster 4 demo on Heroku"/></a></p>
<p align="center">Figure 15. JHipster 4 demo on Heroku</p>
<h2>Learn More</h2>
<p>I hope you've enjoyed learning how JHipster can help you develop hip web applications! It's a nifty project, with an easy-to-use entity generator, a pretty UI and many Spring Boot best-practice patterns. The project team follows five simple <a target="_blank" href="https://jhipster.github.io/policies/">policies</a>, paraphrased here:</p>
<ol>
<li>The development team votes on policies.</li>
<li>JHipster uses technologies with their default configurations as much as possible.</li>
<li>Only add options when there is sufficient added value in the generated code.</li>
<li>For the Java code, follow the default IntelliJ IDEA formatting and coding guidelines.</li>
<li>Use strict versions for third-party libraries.</li>
</ol>
<p>These policies help the project maintain its sharp edge and streamline its development process. If you have features you'd like to add or if you'd like to refine existing features, you can <a target="_blank" href="https://github.com/jhipster/generator-jhipster">watch the project on GitHub</a> and <a target="_blank" href="https://github.com/jhipster/generator-jhipster/blob/master/CONTRIBUTING.md">help with its development</a> and support. We're always looking for help!</p>
<p>Now that you've learned how to use Angular, Bootstrap 4, and Spring Boot with JHipster, go forth and develop great applications!</p>
<h2>Source Code</h2>
<p>The source code for this project is available on GitHub at <a target="_blank" href="https://github.com/mraible/jhipster4-demo">https://github.com/mraible/jhipster4-demo</a>.</p>
<h2>About the author</h2>
<p>Matt Raible is a web developer and Java Champion. He loves to architect and build slick-looking UIs using CSS and JavaScript. When he's not evangelizing <a target="_blank" href="https://stormpath.com">Stormpath</a> and open source, he likes to ski with his family, drive his VWs and enjoy craft beer. He blogs on <a target="_blank" href="https://stormpath.com/blog">stormpath.com/blog</a>, his <a target="_blank" href="https://raibledesigns.com/">personal blog</a>, and you can find him on Twitter (<a target="_blank" href="https://twitter.com/mraible">@mraible</a>). He is a developer on the JHipster team and authored the <a target="_blank" href="https://www.infoq.com/minibooks/jhipster-2-mini-book">JHipster Mini-Book</a> for InfoQ.</p>
<p>Matt will be speaking at Devoxx US in San Jose, California on March 21-23. Plan to attend his two talks: </p>
<ul>
<li><a target="_blank" href="http://cfp.devoxx.us/2017/talk/YKB-3470/What%E2%80%99s_New_in_JHipsterLand">What’s New in JHipsterLand</a>
<li><a target="_blank" href="http://cfp.devoxx.us/2017/talk/JZO-4776/Writing_an_InfoQ_Mini-Book_with_Asciidoctor">Writing an InfoQ Mini-Book with Asciidoctor</a>
</ul>
<div class="bottomitem">
<h3>About the Author</h3>
<div class="row">
<div class="col-sm-12">
<div class="row">
<div class="col-sm-8">
<img class="img-responsive"
src="/community/eclipse_newsletter/2017/january/images/mattraible.jpg"
alt="Matt Raible" />
</div>
<div class="col-sm-16">
<p class="author-name">
Matt Raible<br />
<a target="_blank" href="https://stormpath.com">Stormpath</a>
</p>
<ul class="author-link list-inline">
<li><a class="btn btn-small btn-warning" target="_blank" href="https://twitter.com/mraible">Twitter</a></li>
<li><a class="btn btn-small btn-warning" target="_blank" href="http://raibledesigns.com">Blog</a>
<?php echo $og; ?>
</ul>
</div>
</div>
</div>
</div>
</div>