Documente Academic
Documente Profesional
Documente Cultură
Download Guide
Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and
more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.
• Basic understanding of Java and Spring-based web development and UI development using
HTML, CSS, and JavaScript.
Backdrop
In this article, I will try to create a small end-to-end web application using Java 8 and SpringBoot.
I have chosen SpringBoot because it is much easier to configure and plays well with other tech
stacks. I have also used a REST API and SpringData JPA with an H2 database.
I used Spring Initializer to add all the dependencies and create a blank working project with all my
configurations.
I have used Maven as the build tool, though Gradle can also be used.
pom.xml
1 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XM
LSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.ap
2 ache.org/xsd/maven-4.0.0.xsd">
3 <modelVersion>4.0.0</modelVersion>
4 <groupId>com.example</groupId>
5 <artifactId>bootdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
×
6
7 <packaging>jar</packaging>
8 <name>bootDemo</name>
10 <parent>
11 <groupId>org.springframework.boot</groupId>
12 <artifactId>spring-boot-starter-parent</artifactId>
The 2018 Guide to Java: Features, Improvements, & Updates
13 <version>1.5.3.RELEASE</version>
14 <relativePath />
16 </parent>
17 <properties>
18 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
19 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
20 <java.version>1.8</java.version>
21 </properties>
22 <dependencies>
23 <dependency>
24 <groupId>org.springframework.boot</groupId>
25 <artifactId>spring-boot-starter-data-jpa</artifactId>
26 </dependency>
27 <dependency>
28 <groupId>org.springframework.boot</groupId>
29 <artifactId>spring-boot-devtools</artifactId>
30 </dependency>
31 <dependency>
32 <groupId>org.springframework.boot</groupId>
33 <artifactId>spring-boot-starter-data-rest</artifactId>
34 </dependency>
35 <dependency>
36 <groupId>org.springframework.boot</groupId>
37 <artifactId>spring-boot-starter-web</artifactId>
38 </dependency>
39 <dependency>
40 <groupId>com.h2database</groupId>
41 <artifactId>h2</artifactId>
42 <scope>runtime</scope>
43 </dependency>
44 <dependency>
45 <groupId>org.springframework.boot</groupId>
46 <artifactId>spring-boot-starter-test</artifactId>
47 <scope>test</scope>
48 </dependency>
49 <dependency>
50 <groupId>org.springframework.restdocs</groupId>
51 <artifactId>spring-restdocs-mockmvc</artifactId>
×
52 <scope>test</scope>
53 </dependency>
54 </dependencies>
55 <build>
56 <plugins>
58 <groupId>org.springframework.boot</groupId>
59 <artifactId>spring-boot-maven-plugin</artifactId>
60 </plugin>
61 </plugins>
62 </build>
63 </project>
In the UI part, I have used AngularJS and BootStrap CSS along with basic JS, CSS, and HTML.
I tried to follow the coding guidelines as much as I could, but all suggestions are welcome.
This is a very simple project which can be useful for creating an end-to-end web application.
Package Structure
Implementation ×
Let's start with the SpringBootApplication class.
1 @SpringBootApplication
3 @Autowired
The 2018 Guide to Java: Features, Improvements, & Updates
4 UserRepository userRepository;
5
6 public static void main(String[] args) {
7 SpringApplication.run(BootDemoApplication.class, args);
8 }
9 }
1 @Controller
3 @RequestMapping("/home")
5 return "index";
6 }
7 }
This will act as the homepage for our SPA. Now we create a Controller to handle some REST calls.
1 @RequestMapping("/user")
2 @RestController
4 @Autowired
5 UserService userService;
6
7 @RequestMapping(Constants.GET_USER_BY_ID)
9 return userService.getUserById(userId);
10 }
11
12 @RequestMapping(Constants.GET_ALL_USERS)
14 return userService.getAllUsers();
15 }
16
17 @RequestMapping(value = Constants.SAVE_USER, method = RequestMethod.POST)
19 userService.saveUser(userDto);
20 }
21 }
Here we have different methods to handle different test calls from the client side. ×
I have Autowired a Service class, UserService, in the Controller.
5 }
6
7
8 @Service
10 @Autowired
11 UserRepository userRepository;
12
13 @Override
15 return UserConverter.entityToDto(userRepository.getOne(userId));
16 }
17
18 @Override
20 userRepository.save(UserConverter.dtoToEntity(userDto));
21 }
22
23 @Override
26 }
27 }
In a typical web application, there are generally two types of data objects: DTO (to communicate
through the client) and Entity (to communicate through the DB).
DTO
1 public class UserDto {
2 Integer userId;
3 String userName;
5
6 public UserDto(Integer userId, String userName, List<SkillDto> skillDtos) {
7 this.userId = userId;
8 this.userName = userName;
9 this.skillDtos = skillDtos;
10 }
×
11
12 public UserDto() {
13 }
14
15 public Integer getUserId() {
17 }
18
19 public void setUserId(Integer userId) {
20 this.userId = userId;
21 }
22
23 public String getUserName() {
24 return userName;
25 }
26
27 public void setUserName(String userName) {
28 this.userName = userName;
29 }
30
31 public List<SkillDto> getSkillDtos() {
32 return skillDtos;
33 }
34
35 public void setSkillDtos(List<SkillDto> skillDtos) {
36 this.skillDtos = skillDtos;
37 }
38 }
39
40 public class SkillDto {
41 Integer skillId;
42 String SkillName;
43
44 public SkillDto(Integer skillId, String skillName) {
45 this.skillId = skillId;
46 SkillName = skillName;
47 }
48
49 public SkillDto() {
50 }
51
52 public Integer getSkillId() {
53 return skillId;
54 }
×
55
56 public void setSkillId(Integer skillId) {
57 this.skillId = skillId;
58 }
59
61 return SkillName;
62 }
63
64 public void setSkillName(String skillName) {
65 SkillName = skillName;
66 }
67 }
Entity
1 @Entity
3
4 private static final long serialVersionUID = 0x62A6DA99AABDA8A8L;
5
6 @Column
7 @GeneratedValue(strategy = GenerationType.AUTO)
8 @Id
10 @Column
14
15 public Integer getUserId() {
16 return userId;
17 }
18
19 public void setUserId(Integer userId) {
20 this.userId = userId;
21 }
22
23 public String getUserName() {
24 return userName;
25 }
26
27 public void setUserName(String userName) {
28 this.userName = userName;
29 }
×
30
31 public List<Skill> getSkills() {
32 return skills;
33 }
34
36 this.skills = skills;
37 }
38
39 public User() {
40 }
41
42 public User(String userName, List<Skill> skills) {
43 this.userName = userName;
44 this.skills = skills;
45 }
46 }
47
48 @Entity
50 @Column
51 @GeneratedValue(strategy = GenerationType.AUTO)
52 @Id
54 @Column
56 @ManyToOne
58
59 public Skill(String skillName) {
60 this.skillName = skillName;
61 }
62
63 public Integer getSkillId() {
64 return skillId;
65 }
66
67 public void setSkillId(Integer skillId) {
68 this.skillId = skillId;
69 }
70
71 public String getSkillName() {
72 return skillName;
73 }
×
74
75 public void setSkillName(String skillName) {
76 this.skillName = skillName;
77 }
78
80 return user;
81 }
82
83 public void setUser(User user) {
84 this.user = user;
85 }
86
87 public Skill() {
88 }
89
90 public Skill(String skillName, User user) {
91 this.skillName = skillName;
92 this.user = user;
93 }
94 }
1 @Repository
3 }
4
5 @Repository
7 }
Extending JpaRepository provides a lot of CRUD operations by default, and one can use it to create
their own query methods as well. Please read more about this here.
To convert DTO -> Entity and Entity -> DTO, I created some basic converter classes.
4 user.setUserId(userDto.getUserId());
user.setSkills(userDto.getSkillDtos().stream().map(SkillConverter::dtoToEntity).colle
5 ct(Collectors.toList()));
6 return user;
7 }
8
9 public static UserDto entityToDto(User user) { ×
10 UserDto userDto = new UserDto(user.getUserId(), user.getUserName(), null);
userDto.setSkillDtos(user.getSkills().stream().map(SkillConverter::entityToDto).colle
11 ct(Collectors.toList()));
12 return userDto;
13 }
15
16 public class SkillConverter {
19 Skill.setSkillId(SkillDto.getSkillId());
20 return Skill;
21 }
22
23 public static SkillDto entityToDto(Skill skill) {
25 }
26 }
index.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="ISO-8859-1">
5 <title>Main Page</title>
6 </head>
7 <body ng-app="demo">
8 <hr/>
10 <div class="row">
<label>User</label> <input type="text" ng-model="userDto.userName" class="input
11 -sm spacing"/>
<label>Skills</label> <input type="text" ng-model="skills" ng-list class="input
12 -sm custom-width spacing"
15 </div>
16 <hr/>
17 <div class="row">
18 <p>{{allUsers | json}}</p>
19 </div> ×
20 <hr/>
22 <div class="">
23 <h3>{{user.userName}}</h3>
25 </div>
26 </div>
27 </div>
28 </body>
29 <script src="js/lib/angular.min.js"></script>
30 <script src="js/lib/ui-bootstrap-tpls-2.5.0.min.js"></script>
31 <script src="js/app/app.js"></script>
32 <script src="js/app/UserController.js"></script>
33 <script src="js/app/UserService.js"></script>
36 </html>
While creating the HTML, don't forget to import the required JS and CSS files.
app.js
1 'use strict'
2
3 var demoApp = angular.module('demo', ['ui.bootstrap', 'demo.controllers',
4 'demo.services'
5 ]);
6 demoApp.constant("CONSTANTS", {
7 getUserByIdUrl: "/user/getUser/",
8 getAllUsers: "/user/getAllUsers",
9 saveUser: "/user/saveUser"
10 });
UserController.js
1 'use strict'
2 ×
3 var module = angular.module('demo.controllers', []);
5 function($scope, UserService) {
6
7 $scope.userDto = {
9 userName: null,
10 skillDtos: []
11 };
12 $scope.skills = [];
13
14 UserService.getUserById(1).then(function(value) {
15 console.log(value.data);
16 }, function(reason) {
17 console.log("error occured");
18 }, function(value) {
19 console.log("no callback");
20 });
21
22 $scope.saveUser = function() {
24 return {
25 skillId: null,
26 skillName: skill
27 };
28 });
29 UserService.saveUser($scope.userDto).then(function() {
30 console.log("works");
31 UserService.getAllUsers().then(function(value) {
32 $scope.allUsers = value.data;
33 }, function(reason) {
34 console.log("error occured");
35 }, function(value) {
36 console.log("no callback");
37 });
38
39 $scope.skills = [];
40 $scope.userDto = {
41 userId: null,
42 userName: null,
43 skillDtos: []
44 };
45 }, function(reason) {
46 console.log("error occured");
×
47 }, function(value) {
48 console.log("no callback");
49 });
50 }
51 }
UserService.js
1 'use strict'
2
angular.module('demo.services', []).factory('UserService', ["$http", "CONSTANTS", funct
3 ion($http, CONSTANTS) {
5 service.getUserById = function(userId) {
7 return $http.get(url);
8 }
9 service.getAllUsers = function() {
10 return $http.get(CONSTANTS.getAllUsers);
11 }
12 service.saveUser = function(userDto) {
14 }
15 return service;
16 }]);
app.css
1 body{
2 background-color: #efefef;
3 }
4 span.spacing{
5 margin-right: 10px;
6 }
7 input.custom-width{
8 width: 200px;
9 }
10 input.spacing{
11 margin-right: 5px;
12 }
One simple page will open. Enter the name and skills and the entered data will be persisted in the
DB.
1 spring.mvc.view.prefix = /views/
2 spring.mvc.view.suffix = .html
Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and
more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.
In 2018, a website is one of the most important representations of your business. It provides
visibility, 24/7 accessibility, and is proved to be an effective sales channel.
However, if you want your website to deliver a significant return on investment (ROI), it needs to be
well-designed and built specifically for users' eyes and preferences. Why is that? Let's see.
Picture the following situation: you, as a CEO of your company, should hold a meeting first thing
tomorrow, at 9 AM. Now, would you walk into that meeting completely unprepared and dressed in a
hoodie? Probably not. You would dress for the occasion. So, just like you need to dress to impress
you also need to redesign to shine online.
You need to make a good first impression. No, not good. The best!
Now, we want you to have the best possible "suite" there is and that is why we decided to write about
this year's website redesign tips.
By now you are probably thinking: why shouldn't I just buy a new suit? Precisely, why shouldn't you
start all over again and build a new website?
Well, for starters, you have to be aware that rebuilding a site means creating new databases, dealing
with servers, code and every part of the back-end side. On the contrary, redesigning usually requires
improvements in website's visual elements without making changes in the used technology.
Additionally, rebuilding is a process that can take too much time and resources. Therefore, if
your business website is functioning properly but needs just a bit of touch in design, there is no
point in making a new website. Additionally, by doing a redesign you will minimize costs while
still getting that "fresh look".
• ESPN.com's revenue went up by 35% after they incorporated community suggestions into
their homepage design.
• Eighty-eight percent of online consumers would not return to a website if they had a bad
experience.
• As Invision further states, first impressions are 94% design-related.
What can make a good first (online) impression? Well, a website that is mobile-friendly, that has
good navigation and visible contact information. These are just some basic website redesign tips.
But, where to start? How to make sure your new design gets you more users and leads? It's pretty
simpleーstart with planning. We will cover the planning part in some other article. For now, all you
need to know is without planning the costs can easily go up and the release of the project can be
delayed.
Now, let's get to the actual website redesign tips that will help you be more visible and easily ×
reachable to your users/leads:
Let's check the actual facts. Did you know that slower page load can directly affect your revenue?
More precisely, did you know that it can result in a significant drop in revenue, in some cases 1%
loss for every 100ms delay? If this information didn't make you think maybe this one will:
almost 33% visitors bounce when page speed is 7 seconds long.
Fun fact: There is no difference between page speed and page load time.
These statements just prove that lowering page loading time is one of most significant website
redesign tips you should have in mind.
Want to improve it? Start with checking your current page speed.
So, where to include a web animation? Well, according to Creative Bloq, you can include it in
almost every part of the website. The most popular ones are included in logos or as a background
videos on landing pages. Additionally, keep in mind that adding a hover over a button is always a
good practice, as well.
If you need some inspiration, be sure to check GENROD, Oleg Gert, or Mathis-biabiany.fr.
Why is that?
Well, let's see what Google has to say. In March this year, Google officially announced mobile first
indexing. This means that the mobile version of your website is a starting point which Google
includes in its index (which is how the rankings are determined). But, don't worry, if your site
doesn't have a mobile-friendly version, the desktop one is the one that counts. However, a site that
has a mobile experience will be ranked better than the one that doesn't have.
Making your website mobile-friendly is one of the best website redesign tips we can give you.
You might think that quality content has a way to find its path to users' hearts. Although it is trueー
quality content can attract more usersーit is not nearly enough. A content has to be optimized for
both browsers and readers. It has to be Google-friendly while still being easily readable.
If you are a skeptic, check the facts! According to Hubspot, 61% of marketers pay attention to SEO to
grow their organic presence. Additionally, 40% of marketers agree that the toughest task in SEO is
adapting to changes in search algorithms.
In order to make this process a bit easier you should know that, for 2018, one of the biggest website
(re)design tips is adding Robots Meta tags, which provide search engines with instructions on
how a content should be indexed and presented in results. None of the Meta Robots tags are visible
to website visitors but can work wonders.
What is a conversion rate optimization? According to Moz.com, this type of optimization consists of
ways to increase the number of visitors who are willing to take an action. creating your landing
pages so a user can easily contact you, make a purchase or make any other move. In short: this is
one of the website redesign tips that is going to help users reach your CTA in no-time.
×
So, what do you need to do in order to have the right CRO? Analyze how users move through the site
and which actions they take. Is there anything that is stopping them from making a conversion?
Let's back up a bit. What is a flat design? This is a minimalistic graphics style that uses features
in a two-dimensional space. If you can remember, 2000s were full of graphic website elements.
Suddenly, the times changed一a minimalistic, 1.0 approach to design was supposed to offer the best
user experience. However, it didn't manage to deliver. Although it was created as an approach that
will lead a user to call-to-action, somehow users missed CTAs and were even more confused.
Now, the second version of the flat design is full of gradients, highlights, and shadows. Flat
design 2.0 is all about making depth and getting the 3D, real-feel of this type of design.
One of the best website redesign tips we can give you: be sure to include it. You won't regret it.
So, where should you put social media links? Well, it's up to you to decide whether you want to go
with top, middle, or the bottom of a webpage. However, the important thing is to make those links
open in a new window, so your visitors don't leave the website.
Currently, one of the major web design trends is a gradient. In 2018, gradient moved towards
typography. If this sounds too plain to you, consider adding a gradient highlight. On the other hand,
if you are not feeling this gradient trend don't worry一there's a backup plan. Try adding image-
filled typography to your landing page. You'll see, it can make quite a difference and give a
modern feel to your website.
If these trends did not impress you or just don't go along with what you had in mind, be sure to
check the Design's Hack article to find the one trend that will suit you the best.
When it comes to choosing colors, there are no website redesign tips you should follow. That being
said, we have to mention a color of the yearーUltra Violet (18-3838). The good thing about
purple is that you can use it muted, saturatedーit is easily adaptable to any industry.
Check out these examples on image-filled typography (Nurture Digital) and using purple in the
design (Neurohive.io).
Let's check the statistics. According to AppInstitute, user engagement can be increased by 136%,
while conversions can increase up to 52% when you include PWA in your web design.
So, what should you include in a PWA? Should you add push notifications or animated page
transitions? Or both, perhaps? Well, our advice is this: try to mix the best sides of websites and
apps to get the greatest results. In fact, don't think too much about it. Let the designer handle it.
He/she should know how to include these elements and create a perfect user experience (UX).
And that's it! These are the 10 website redesign tips you should bear in mind.
Here are some questions you should ask yourself while testing:
If you have positive answers to all these questions (and many more) and feel you can move on to the
launch.
Once you launch the website, our advice is to never stop testing and improving. How are you going ×
to manage that? Add a survey regarding the new design on your website and acquire users' opinions
first hand.
Whether you decide to go with a development company or a freelancer please make sure you found
the right one. A good web designer knows all the principles of web design and how to meet
previously defined goals.
What is your experience with redesigning a website? Did you implement all these tips? Do you
have anything to add?
Topics: WEB DEV, DESIGN, REDESIGN, LOADING TIME, SEO, OPTIMIZATION, FLAT DESIGN 2.0, PWA
Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and
more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.
Developers already know of Ruby as one of the most popular and beloved programming languages
in the world. And while it's not the hot new language anymore, it continues to power well-known
applications like Twitch, SoundCloud, and Hulu, as well as the project-management tool Basecamp,
open-source repository GitHub, and the hospitality marketplace Airbnb.
At its core, Ruby's value is that it allows developers to write less code while accomplishing more
than other languages and frameworks. The challenge is that Ruby on Rails, the primary framework
for the Ruby language, is "opinionated software." It codifies under the assumption that there is "a
best way to do things," and encourages users to design that way (and in some cases to discourage
alternatives).
If you specialize and invest the time in learning how to develop with Ruby, you'll find that it's quite
easy to get comfortable and efficient. "The Rails Way" leads to a tremendous increase in
productivity. However, if you try and bring old habits from other languages into your Rails
development, you'll likely have a more challenging experience.
Luckily there are plenty of tools to help Ruby developers dive right in and stay efficient when
building applications. But first, let's look at Ruby on Rails.
• Don't repeat yourself (DRY): The DRY principle of software development states that,
"Every piece of knowledge must have a single, unambiguous, authoritative representation
within a system." This is one of the assumptions Ruby developers start with. By not having to
write the same information over and over again, your code is more maintainable, more
extensible, and far less prone to bugs.
• Convention over configuration: Ruby on Rails favors what it believes to be the best way
to build web applications. When using Ruby, developers need to have these practices as a
default set of conventions. This enables you to deploy applications faster rather than having
teams spend time endlessly configuring files. ×
1. Four Days On Rails: This toolkit is a condensed guide to Ruby on Rails that aims to give
developers everything they need to know to start building applications in just four days. It can be a
great resource for developers looking to understand the fundamental philosophies and “best-
practice” assumptions at the heart of Ruby.
Authenticating Users
There are multiple Ruby tools available to add user authentication to your app. The three tools
below are completely free and open-source. Visit their GitHub pages to learn how to implement.
2. Devise: Devise enables you to build apps that easily authenticate users. Everything from email
confirmation, password recovery, and processing requests from multiple user sessions
simultaneously.
3. Clearance: This is a similar tool to Devise mentioned above, but much simpler. Clearance is
good for just basic email/password authentication setup.
4. CanCanCan: CanCanCan allows you to grant access rules to users regarding their data. It also
enables controller helpers that simplify the code in Rails controllers by performing the loading and
checking of permissions in your application’s controllers.
Global Location
Building an app for the world stage? Check out the following location tools for Ruby. Again, these
tools are free, open-source, and available on GitHub.
5. Geocoder: Geocoder allows you to handle building applications that may require specific geo-
locations. It provides an easy integration with several geocoding APIs and is easily integrated into
Rails.
6. Globalize: With Globalize, you can store translations to your data for any locale you want, and
pull that data automatically from a physical or cloud database.
Front-End Formatting
Ruby on Rails can be used for both front-end and backend development. If you're using Ruby for
×
front-end, you'll need additional tools to get the look you want. Check out these formatting tools for
help:
7. Bootstrap: Bootstrap is essentially a component library, a great resource for both enterprise-
level software teams as well as early start-ups looking to build apps with responsive formatting and
styling elements.
9. Formtastic: Formtastic is a quick way to add responsive forms to your app. With the flexibility
to style it as you like, and support multiple models in the same form, it’s a great tool for any web
app.
Data
If your application includes data collection or uses a database, you'll want to use one of the following
open-source tools.
10. PaperTrail: An easy tool that allows you to keep track of all changes in your app’s data. Simple
and effective.
11. Audited: Similarly simple to PaperTrail, but with a bit more flexibility in what data you can
collect.
12. Paperclip: This tool builds integration for saving files in your app. It is effective for simple
apps to get rolling but may not be robust enough for enterprise-level applications looking to scale.
Testing
The Ruby community has developed useful testing tools to help you optimize your application.
These tools can find bugs, security vulnerabilities, and save you time by simulating test scenarios.
Check out these open source tools:
13. RSpec: RSpec remains a classic testing tool because it is compatible with all the other test-
related tools. RSpec also lets developers have more readability by providing more documentation
and web examples than other testing tools.
14. Faker: This tool generates random test data for your application. This can save lots of time
because you won’t need to waste time writing fake data. Since faker generates data randomly, your
team can easily experiment with a number of variables to test your app's performance.
15. RuboCop: This is a popular code testing tool across the Ruby community. By defining a list of
rules—or “Cops” for your Ruby project, you can check code for specific style, metric, and controller
issues. This tool can also check for automatic fixes and report them before deployment—all with the
goal to save your team time.
16. Brakeman: This testing tool helps developers find security vulnerabilities and is particularly
valuable for both startups and enterprises handling transactional data. Easily spot issues with SQL
injection and unsafe redirects that could potentially be flaws in your application.
×
Dive Into Ruby
Ruby on Rails may seem like an esoteric programming framework, but both large-scale web
applications and startups can benefit from its focused approach to delivering quick builds.
Developers can focus on building flexible web applications by incorporating the various tooling APIs
from the continuously-growing Ruby development community.
The 2018 Guide to Java: Features, Improvements, & Updates
It looks like a steep learning curve to get started, but Ruby offers developers time-saving techniques
in the long run, all based on the simple principles of a simple convention.
Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and
more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.
Topics: WEB DEV, RUBY ON RAILS, BOOTSTRAP, WEB APPLICATION DEVELOPMENT, DEVELOPER TOOLS
Published at DZone with permission of Ben Putano , DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.