Documente Academic
Documente Profesional
Documente Cultură
Introduction
JavaLite is a collection of frameworks for simplifying common tasks that
every developer has to deal with when building applications.
In this tutorial, we’re going to take a look at JavaLite features focused on
building a simple API.
2. Setup
Throughout this tutorial, we’ll create a simple RESTful CRUD application. In
order to do that, we’ll use ActiveWeb and ActiveJDBC – two of the
frameworks that JavaLite integrates with.
So, let’s get started and add the first dependency that we need:
1 <dependency>
2 <groupId>org.javalite</groupId>
3 <artifactId>activeweb</artifactId>
4 <version>1.15</version>
</dependency>
5
ActiveWeb artifact includes ActiveJDBC, so there’s no need to add it
separately. Please note that the latest activeweb version can be found in
Maven Central.
The second dependency we need is a database connector. For this
example, we’re going to use MySQL so we need to add:
1 <dependency>
2 <groupId>mysql</groupId>
3 <artifactId>mysql-connector-java</artifactId>
4 <version>5.1.45</version>
</dependency>
5
Again, latest mysql-connector-java dependency can be found over on Maven
Central.
The last dependency that we have to add is something specific to JavaLite:
1
2 <plugin>
3 <groupId>org.javalite</groupId>
<artifactId>activejdbc-instrumentation</artifactId>
4 <version>1.4.13</version>
5 <executions>
6 <execution>
7 <phase>process-classes</phase>
8 <goals>
<goal>instrument</goal>
9 </goals>
10 </execution>
11 </executions>
12 </plugin>
13
The latest activejdbc-instrumentation plugin can also be found in Maven
Central.
Having all this in place and before starting with entities, tables, and
mappings, we’ll make sure that one of the supported databases is up and
running. As we said before, we’ll use MySQL.
Now we’re ready to start with object-relational mapping.
3. Object-Relational Mapping
or:
1 List<Product> products = Product.findAll();
This is where activejdbc-instrumentation plugin comes in. As we already
have the dependency in our pom, we should see classes being instrumented
during build:
1 ...
2 [INFO] --- activejdbc-instrumentation:1.4.11:instrument (default) @ javalite ---
3 **************************** START INSTRUMENTATION ****************************
4 Directory: ...\tutorials\java-lite\target\classes
5 Instrumented class: .../tutorials/java-lite/target/classes/app/models/Product.class
**************************** END INSTRUMENTATION ****************************
6 ...
7
Next, we’ll create a simple test to make sure this is working.
3.2. Testing
Finally, to test our mapping, we’ll follow three simple steps: open a
connection to the database, save a new product and retrieve it:
1 @Test
2 public void givenSavedProduct_WhenFindFirst_ThenSavedProductIsReturned() {
3
Base.open(
4 "com.mysql.jdbc.Driver",
5 "jdbc:mysql://localhost/dbname",
6 "user",
7 "password");
8
9 Product toSaveProduct = new Product();
toSaveProduct.set("name", "Bread");
10 toSaveProduct.saveIt();
11
12 Product savedProduct = Product.findFirst("name = ?", "Bread");
13
14 assertEquals(
15 toSaveProduct.get("name"),
16 savedProduct.get("name"));
}
17
18
19
Note that all this (and more) is possible by only having an empty model and
instrumentation.
4. Controllers
Now that our mapping is ready, we can start thinking about our application
and its CRUD methods.
For that, we’re going to make use of controllers which process HTTP
requests.
Let’s create our ProductsController:
1 @RESTful
2 public class ProductsController extends AppController {
3
4 public void index() {
5 // ...
}
6
7 }
8
With this implementation, ActiveWeb will automatically map index() method
to the following URI:
http://<host>:<port>/products
Controllers annotated with @RESTful, provide a fixed set of methods
automatically mapped to different URIs. Let’s see the ones that will be
useful for our CRUD example:
5. Configuration
ActiveWeb is based mostly on conventions, project structure is an example
of that. ActiveWeb projects need to follow a predefined package layout:
1
2 src
|----main
3 |----java.app
4 | |----config
5 | |----controllers
6 | |----models
|----resources
7 |----webapp
8 |----WEB-INF
9 |----views
10
There’s one specific package that we need to take a look at – app.config.
Inside that package we’re going to create three classes:
1 public class DbConfig extends AbstractDBConfig {
2 @Override
3 public void init(AppContext appContext) {
4 this.configFile("/database.properties");
}
5 }
6
This class configures database connections using a properties file in the
project’s root directory containing the required parameters:
1 development.driver=com.mysql.jdbc.Driver
2 development.username=user
3 development.password=password
development.url=jdbc:mysql://localhost/dbname
4
This will create the connection automatically replacing what we did in the
first line of our mapping test.
The second class that we need to include inside app.config package is:
1 public class AppControllerConfig extends AbstractControllerConfig {
2
3 @Override
4 public void init(AppContext appContext) {
5 add(new DBConnectionFilter()).to(ProductsController.class);
}
6
}
7
This code will bind the connection that we just configured to our
controller.
The third class will configure our app’s context:
1 public class AppBootstrap extends Bootstrap {
2 public void init(AppContext context) {}
3 }
After creating the three classes, the last thing regarding configuration
is creating our web.xml file under webapp/WEB-INF directory:
1
2
<?xml version="1.0" encoding="UTF-8"?>
3 <web-app xmlns=...>
4
5 <filter>
6 <filter-name>dispatcher</filter-name>
7 <filter-class>org.javalite.activeweb.RequestDispatcher</filter-class>
<init-param>
8 <param-name>exclusions</param-name>
9 <param-value>css,images,js,ico</param-value>
10 </init-param>
11 <init-param>
12 <param-name>encoding</param-name>
<param-value>UTF-8</param-value>
13 </init-param>
14 </filter>
15
16 <filter-mapping>
17 <filter-name>dispatcher</filter-name>
<url-pattern>/*</url-pattern>
18
</filter-mapping>
19
20 </web-app>
21
22
Now that configuration is done, we can go ahead and add our logic.
7. Views
ActiveWeb uses FreeMarker as a templating engine, and all its templates
should be located under src/main/webapp/WEB-INF/views.
Inside that directory, we will place our views in a folder
called products (same as our controller). Let’s create our first template
called _product.ftl:
1 {
2 "id" : ${product.id},
"name" : "${product.name}"
3 }
4
It’s pretty clear at this point that this is a JSON response. Of course, this
will only work for one product, so let’s go ahead and create another
template called index.ftl:
1 [<@render partial="product" collection=products/>]
This will basically render a collection named products, with each one
formatted by _product.ftl.
Finally, we need to bind the result from our controller to the
corresponding view:
1
2 @RESTful
3 public class ProductsController extends AppController {
4
5 public void index() {
List<Product> products = Product.findAll();
6 view("products", products);
7 render();
8 }
9
10 public void show() {
String id = getId();
11 Product p = Product.findById(id);
12 view("product", p);
13 render("_product");
14 }
15 }
16
In the first case, we’re assigning products list to our template collection
named also products.
Then, as we’re not specifying any view, index.ftl will be used.
In the second method, we’re assigning product p to element product in the
view and we’re explicitly saying which view to render.
We could also create a view message.ftl:
1 {
2 "message" : "${message}",
3 "code" : ${code}
}
4
And then call it form any of our ProductsController‘s method:
1 view("message", "There was an error.", "code", 200);
2 render("message");
9. Conclusion
JavaLite has a lot of tools to help developers get an application up and
running in minutes. However, while basing things on conventions results in
a cleaner and simpler code, it takes a while to understand naming and
location of classes, packages, and files.
This was only an introduction to ActiveWeb and ActiveJDBC, find more
documentation on their website and look for our products application in the
Github project.