{"id":19719986,"url":"https://github.com/timboudreau/acteur-wicket","last_synced_at":"2026-05-15T22:03:35.726Z","repository":{"id":27064965,"uuid":"30531136","full_name":"timboudreau/acteur-wicket","owner":"timboudreau","description":"Run apache wicket applications without a servlet container, in Netty + Acteur","archived":false,"fork":false,"pushed_at":"2015-02-10T03:03:24.000Z","size":224,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-31T00:57:26.262Z","etag":null,"topics":["async","guice","netty","wicket"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/timboudreau.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-02-09T10:43:56.000Z","updated_at":"2018-12-09T00:10:24.000Z","dependencies_parsed_at":"2022-08-31T19:40:52.845Z","dependency_job_id":null,"html_url":"https://github.com/timboudreau/acteur-wicket","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/timboudreau/acteur-wicket","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timboudreau%2Facteur-wicket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timboudreau%2Facteur-wicket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timboudreau%2Facteur-wicket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timboudreau%2Facteur-wicket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/timboudreau","download_url":"https://codeload.github.com/timboudreau/acteur-wicket/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timboudreau%2Facteur-wicket/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279006759,"owners_count":26084148,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","guice","netty","wicket"],"created_at":"2024-11-11T23:09:53.080Z","updated_at":"2025-10-11T08:17:45.894Z","avatar_url":"https://github.com/timboudreau.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"acteur-wicket\n=============\n\nRun Wicket applications without a servlet container or any servlets at all.\n\nExperimental integration of [Apache Wicket](http://wicket.apache.org) into \n[Acteur](http://timboudreau.com/blog/updatedActeur/read);  at this point not very\ndeveloped, but works to run a single-page test application\n(run the class `WicketActeurModuleTest` in the test packages).\n\nThis means running Wicket applications without any servlets or servlet containers,\nusing [Netty](http://netty.io) and [Acteur](http://timboudreau.com/blog/updatedActeur/read)\nto handle the plumbing of network I/O and HTTP protocol.\n\nPlenty to do on it, but the basics work, so it has some promise.\n\nUnfortunately, most Wicket applications routinely cast to `HttpServletRequest`\nand `ServletWebRequest`;  even Wicket's internals assume a `WicketFilter` is\npresent (we mock this with `FakeWicketFilter`).  Things that make the assumption\nthat they're running in a servlet container and blindly cast will fail.\n\n\nWhy?\n----\n\n * Application startup times of 1-5 seconds, for one thing\n * If you use Acteur's API, the ability to asynchronously write a response a chunk at a time, getting called\nback when one chunk has been flushed to the socket.\n * Microscopic memory footprint, as compared with most application servers\n(wicket definitely adds memory requirements;  a small Acteur application such\nas [tiny-maven-proxy](https://github.com/timboudreau/tiny-maven-proxy) can run\nin 7Mb).\n * No XML - and not because something is generating it under the hood - your\nserver is a program and you can run it, period.  Flexible configuration can be\ndone using properties files (uses [Giulius](https://github.com/timboudreau/giulius) under the hood)\n\n\nUsage\n-----\n\nStartup is done the same way it is done with Acteur - just have a main method,\ncreate a settings with any configuration you want to load, create a ServerBuilder\nwith it, build your server and start it.\n\nUnlike with servlet containers, there is *no* XML, deployment descriptors\nor similar (if you think that's a bad thing, this project is not for you).\n\nHere is the startup code for the example, \n[WicketActeurModuleTest](https://github.com/timboudreau/acteur-wicket/blob/master/acteur-wicket/src/test/java/com/mastfrog/acteur/wicket/WicketActeurModuleTest.java#L42) in the\ntests classes:\n\n```java\n    public static void main(String[] args) throws Exception {\n        // All of these settings can be overridden by\n        // values in /etc/acteur-wicket.properties, /opt/local/etc/acteur-wicket.properties,\n        // ~/acteur-wicket.properties and ./acteur-wicket.properties in that order,\n        // or by command-line arguments in the form, e.g. --port 8080\n        Settings settings = new SettingsBuilder(\"acteur-wicket\")\n                .add(ServerModule.PORT, \"5757\") // set the default port\n                .add(PathFactory.EXTERNAL_PORT, \"5757\") // ensures redirects go to the local port\n                .addFilesystemAndClasspathLocations()\n                .parseCommandLineArguments(args)\n                .build();\n\n        Server server = new ServerBuilder(\"acteur-wicket\")\n                .add(HomePageApplicationModule.class)\n                .add(settings)\n                .enableOnlyBindingsFor(BOOLEAN, INT, LONG) // minor optimization\n                .build();\n        server.start();\n    }\n\n    static class HomePageApplicationModule extends WicketActeurModule {\n\n        // ServerBuilder can instantiate a module which takes a ReentrantScope\n        // Settings or both in its constructor - the scope is part of the way\n        // Acteur creates dynamic constructor arguments using request contents\n        HomePageApplicationModule(ReentrantScope scope) {\n            super(NavomaticApplication.class, scope);\n        }\n    }\n```\n\n\nThe Code\n--------\n\nThe meat of the code that is not adapters for Wicket and Servlet API classes is in\n\n * `WicketApplicationInitializer` - does the things WicketFilter does to get\nthe application ready for use, does a few hacks to set the page factory\n * `WicketActeur` - dispatch acteur which invokes the `RequestCycle`\n * `EnsureSessionId` - acteur called before `WicketActeur` to ensure every request has a session id\n * `ActeurSessionStore` - session storage - for now, just maintains a concurrent hash map, but the backing\nstorage could be made pluggable\n\n\nThings That Are Different\n-------------------------\n\n * Acteur uses Guice, so this does too.  Page and application are instantiated with Guice.  Note\nthis does not use the Wicket-Guice project - only pages and the application use Guice directly\n(wicket guice mainly does field injection, which is of limited usefulness in a framework that does\nmost of its work in constructors).  Any class that Acteur allows you to inject can be injected\ninto the constructor of a page or the application.  `PageParameters` work normally.\n * Acteur won't have built-in support for HTTPs until the cleaner API in Netty 5 is available, so\nall requests are assumed to be HTTP.  The recommendation with Acteur is to do your HTTPs via a\nreverse proxy such as NginX, which also lets you do clean zero-downtime redeployment by starting\nthe new application on another port and then updating NginX's configuration and shutting down the\nold one\n * The equivalent of a servlet/filter path can be set by setting the setting `basePath` (or passing\n`--basepath /some/path` in the above example\n\n\nTo-Do\n-----\n\n * Test with some real applications and fix things\n * [acteur-resources](https://github.com/timboudreau/acteur/tree/master/acteur-resources) has good \nsupport for serving static files that should be integrated - right now these need to be mounted with code\n\n\nPackaging And Deployment\n------------------------\n\nUse Acteur's [maven-merge-configuration](https://github.com/timboudreau/tiny-maven-proxy/blob/master/pom.xml#L103)\nplugin to build a merged JAR which automatically coalesces Acteur's generated files and things like\n`META-INF/services` files (say, if you have need JDBC drivers) - see the link above - configuration consists\nof setting the main class name.\n\nThen run it with good old `java -jar`.\n\n\nThings You Get For Free Using Acteur Under The Hood\n---------------------------------------------------\n\n * Use the [statistics](https://github.com/timboudreau/giulius-web/tree/master/statistics) library to create\nJMX MBeans with a few annotations on any object created by Guice\n * Use the [statsd-aop](https://github.com/timboudreau/giulius-web/tree/master/statsd-aop) integration to\nfire metrics at a [statsd](https://github.com/etsy/statsd/) server by annotating methods on Guice-created objects\n * Use [acteur-jdbc](https://github.com/timboudreau/acteur/tree/master/acteur-jdbc) for easy JDBC integration (uses BoneCP)\n * Trivially add [bunyan compatible JSON logging](https://github.com/timboudreau/bunyan-java)\n * Easy to integrate with [mongodb](https://github.com/timboudreau/acteur/tree/master/acteur-mongo)\n\n\nWhy Would You Want To Get Rid Of Your Servlet Container?\n--------------------------------------------------------\n\nServlet containers are obsolete.  In the days when a powerful server might have 64Mb of memory, it made sense\nto cram as many web applications into one process as possible.  Today, you're very likely deploying an entire\nvirtual OS - *that's* your container.  They're an optimization for a world that no longer exists.\n\nSecondly, startup time for many of them is painfully slow.  The usual answer is to use JRebel or similar to\nhot-load code.  What if your server started so fast you didn't even *care* about hot-loading code?  You could\nsee that for what it is - a hack to work around a broken environment.  NodeJS and Netty users enjoy those kinds\nof startup times today.  You can too.\n\nThirdly, Java EE is the legacy of an era when the industry had an unhealthy fetish for XML - and a thing\ndesigned when nobody knew what the web would *become*.  Descriptors are\npainful to work with, verbose, overkill for most configuration needs, and difficult to modify at deployment-time.\n\nForthly, while Java EE is trying to add asynchronous I/O now, the ecosystem has thread-per-socket, synchronous I/O\nbaked into its bones.  While Wicket is part of that world and assumes blocking I/O, if it ever hopes to escape\nfrom that world, something like this is how it will happen.\n\nIn short, you escape from a world of legacy bloat, and return to a world where your code is a program, and you\ncan run it - without needing to draw a pentagram on the floor, stand in it and draw XML tags in the air.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimboudreau%2Facteur-wicket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimboudreau%2Facteur-wicket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimboudreau%2Facteur-wicket/lists"}