Framework
jfinal/jfinal avatar
jfinal/jfinal

JFinal: A Compact Java Web and ORM Framework with Zero XML Configuration

JAVA WEB + ORM Framework

3,269 stars1,289 forksJavaApache-2.0

At a glance

What is it?
JFinal is a Java web framework built around an MVC architecture, a Convention over Configuration approach, and an ActiveRecord-based ORM. Its entire distribution is 832 KB with no third-party dependencies, and it supports zero XML configuration. It is aimed at Java developers who want the development speed of dynamic languages like Ruby or Python while staying on the JVM.
Who is it for?
JFinal suits Java teams that want a lightweight, convention-driven framework with a minimal dependency footprint and fast development cycles, particularly for domestic Chinese web projects where its community support is strongest. It is a poor fit for teams that need the broad ecosystem integrations of Spring Boot, the standardized microservice tooling that Spring Cloud provides, or compatibility with Spring-centric third-party libraries.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 12 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What JFinal Is and Who It Targets

JFinal targets Java developers who find mainstream enterprise frameworks overly complex for the size of project they are building. Its stated design goals are fast development, minimal code volume, simple learning curve, and a lightweight footprint. The README lists Restful architecture as one of those goals alongside the others.

The framework's pitch is explicit: the README says it aims to give Java developers the development efficiency of Ruby and Python while keeping the type safety and ecosystem of Java. This positions it as a productivity-focused alternative to larger frameworks, not as a replacement for their enterprise feature sets.

Adding JFinal to a Maven Project

JFinal is distributed as a single Maven artifact. Add it to a project with:

java
<dependency>
    <groupId>com.jfinal</groupId>
    <artifactId>jfinal</artifactId>
    <version>5.3.0</version>
</dependency>

The README states the distribution is 832 KB with no third-party dependencies. This is the complete framework in a single jar, which has implications for deployment packaging and startup time.

MVC Architecture and the Blog Controller Example

JFinal follows a Convention over Configuration approach to routing. A controller extends `Controller`, and public methods on that class become action handlers. The README shows a blog management controller:

java
@Before(BlogInterceptor.class)
public class BlogController extends Controller {

    @Inject
    BlogService service;

    public void index() {
        set("blogPage", service.paginate(getInt(0, 1), 10));
        render("blog.html");
    }

    @Before(BlogValidator.class)
    public void save() {
        getModel(Blog.class).save();
        redirect("/blog");
    }
}

The `@Before` annotation applies interceptors per method or per class. The `@Inject` annotation handles dependency injection. Methods call `getModel()`, `set()`, and `render()` directly, since `Controller` provides these as inherited methods. No XML mapping is required; the framework derives URL routes from the class and method names by convention.

ActiveRecord ORM: Db + Record and Model

JFinal offers two complementary database access patterns. The Db + Record mode provides a SQL-oriented API where you write queries directly and receive generic Record objects. The ActiveRecord mode wraps a database table in a typed Java class that extends `Model<T>`.

The README shows a Blog model that requires zero configuration:

java
public class Blog extends Model<Blog> {

}

With that single class, the framework maps the `blog` table automatically by convention. The service layer then uses the model's built-in methods:

java
public Page<Blog> paginate(int pageNumber, int pageSize) {
    return dao.paginate(pageNumber, pageSize, "select *", "from blog order by id asc");
}

The `paginate` method splits the query into a select clause and a from clause, which allows the framework to build both a data query and a count query from the same call. The README describes this as the "Db + Record mode" being flexible and the ActiveRecord mode being fast.

Validation, Interceptors, and the Enjoy Template Engine

JFinal includes a server-side validation system based on a Validator class. Validators are wired to controller actions via the `@Before` annotation. The README shows a BlogValidator:

java
public class BlogValidator extends Validator {
    protected void validate(Controller controller) {
        validateRequiredString("blog.title", "titleMsg", "Please enter a Blog title!");
        validateRequiredString("blog.content", "contentMsg", "Please enter Blog content!");
    }

    protected void handleError(Controller controller) {
        controller.keepModel(Blog.class);
    }
}

The interceptor system allows cross-cutting concerns to be applied before or after any action. The README shows an example interceptor that logs the action key before and after invocation, demonstrating the AOP mechanism.

For views, JFinal provides the Enjoy template engine as its default, with FreeMarker and JSP also supported. The README claims Enjoy can be learned to 90 percent proficiency within ten minutes. Whether that holds depends on the team's prior template experience, but the API is deliberately minimal.

A significant development-time feature is hot reload: modified Java source files are automatically reloaded without restarting the server during development. The README lists this as a built-in feature, not an external tool requirement.

The Plugin System and Hot Reload in Development

JFinal's extensibility is built around a plugin system rather than a starter ecosystem. A plugin is a Java class that implements the `IPlugin` interface and is registered in the application's configuration class. The framework calls `start()` on each plugin when the application starts and `stop()` when it shuts down. This lifecycle hook makes plugins a natural place for connection pool initialization, cache warming, and third-party service configuration.

The README lists the plugin architecture as one of the framework's design goals under extensibility. Third-party JFinal plugins exist for common integration targets, but the plugin catalog is smaller than the Spring Boot starter ecosystem by a substantial margin, which is a practical constraint for teams that need integrations with less common services.

The hot reload feature is implemented directly in the framework and does not require an external agent or build tool. When running in development mode, JFinal monitors the classpath for changed Java files and reloads them automatically. The README presents this as a built-in capability that eliminates the restart cycle during development. The behavior applies to the main classpath; changes to static resources like templates and CSS are generally visible without a reload in any web framework, but Java class changes typically require a restart in standard setups.

The AOP support works through the interceptor mechanism. Interceptors implement the `Interceptor` interface and override an `intercept` method. The `@Before` annotation on a controller class or method applies one or more interceptors to all actions or a specific action. The README shows an example where the interceptor prints the action key before and after calling `inv.invoke()`, which is the standard pattern for surrounding an action with cross-cutting behavior like logging, authorization checks, or transaction management.

Limitations and Comparison with Spring Boot

JFinal's design focus on simplicity has a direct cost. It does not participate in the Spring ecosystem. Teams that need Spring Security, Spring Data, Spring Cloud service discovery, or the large library of Spring-compatible third-party integrations will find JFinal incompatible with those tools.

Spring Boot is the dominant Java web framework globally. It is backed by VMware Broadcom, has a large international community, and provides production-ready auto-configuration for hundreds of integrations. The difference in approach is that Spring Boot applies a full dependency injection container and convention-based auto-configuration across the entire application, while JFinal provides a more direct, framework-controlled execution model with fewer abstractions. Spring Boot applications also have significantly larger artifact sizes and startup overhead by comparison, but the ecosystem breadth justifies that cost for most enterprise projects.

JFinal's 832 KB footprint is a real advantage for applications where startup time, memory, or deployment packaging size matters, but this advantage is relevant mainly in contexts where Spring Boot's auto-configuration overhead would be a noticeable burden.

JFinal does not provide an embedded server configuration mechanism comparable to Spring Boot's application.properties-driven port and context path settings. Server configuration is handled at the web container level, which means deploying JFinal typically means packaging a WAR file and deploying to Tomcat, Jetty, or another servlet container, rather than running a self-contained JAR with an embedded server. The README does not document an embedded server path, so teams that want a single-JAR deployment model should verify this against the JFinal documentation before committing.

Maintenance and License

The last push was on 2026-09-18. The repository has no GitHub releases; versioning is managed via Maven Central. The current version listed in the README Maven coordinates is 5.3.0. The project is Apache-2.0 licensed. The official website is jfinal.com, which hosts the Chinese-language documentation and community. The README is written in Chinese and links to a separate English README file in the repository.

Editorial conclusion

JFinal suits Java teams that want a lightweight, convention-driven framework with a minimal dependency footprint and fast development cycles, particularly for domestic Chinese web projects where its community support is strongest. It is a poor fit for teams that need the broad ecosystem integrations of Spring Boot, the standardized microservice tooling that Spring Cloud provides, or compatibility with Spring-centric third-party libraries. Before adopting JFinal, verify that the Enjoy template engine meets your view requirements if you are not using JSP, and confirm that the project's development pace matches the Java version your team targets, since the README and documentation site are primarily in Chinese.

Frequently asked questions

Does JFinal require any XML configuration files?

No. The README explicitly lists zero XML configuration as a design goal. Routing, ORM mappings, and view resolution are handled by convention rather than XML descriptors.

Can JFinal be used with Spring libraries or Spring Boot starters?

JFinal does not use the Spring container, so Spring Boot starters and Spring-dependent libraries are not compatible. JFinal has its own plugin system and dependency injection mechanism separate from Spring's.

What database types does JFinal support?

The README does not specify which databases are supported beyond showing MySQL-style SQL in examples. The Db + Record and ActiveRecord patterns accept standard JDBC connections, so compatibility depends on what the underlying JDBC driver supports, not on JFinal itself.

Official sources

  1. Issues
  2. jfinal/jfinal on GitHub
  3. License: Apache-2.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jfinal-jfinal.svg)](https://hysenlabs.com/projects/jfinal-jfinal)