Building a Secure Java EE Application with NetBeans Annotations
Enterprise Java development leans heavily on declarative security, and NetBeans remains one of the most productive environments for putting that model into practice. With a handful of annotations, you can lock down session beans and web endpoints without filling the codebase with cross-cutting boilerplate.
Developers across Sydney, Melbourne, and Brisbane still gather at local Java user groups where NetBeans often comes up for its straightforward project wizards. The IDE handles enterprise archives and Javadoc generation without the licence headaches of competing tools, which suits Australian studios working on government and finance projects.
Security annotations such as @RolesAllowed, @DenyAll, @PermitAll, and @DeclareRoles let you express authorisation policies directly next to the code they protect. Compared with XML-heavy descriptors, this keeps intent readable from within the editor.
The walk-through below takes a fresh enterprise project from an empty workspace through to a role-protected service running on a common application server, with patterns that fit both single-machine prototypes and multi-node staging environments hosted in an Australian region.
Preparing the project structure in NetBeans
Open NetBeans and start a new Java EE project, selecting "Enterprise Application" from the New Project wizard. Name the project SecureShop and accept the default GlassFish server bundled with the IDE, or pick Payara if your team already standardises on it.
Create two sub-modules: an EJB module for the business tier and a Web module for the presentation layer. NetBeans wires the enterprise archive to depend on both, which keeps packaging clean when you later deploy to staging.
Defining a security domain and identity store
Before annotations can take effect, the application server needs a realm to authenticate against. The bundled file realm works for local development, while a JDBC realm backed by an AU-hosted Postgres instance is a sturdier choice for production-style testing in Sydney data centres.
Configure the realm through the server admin console or by dropping a domain.xml fragment into your local profile. Seed at least two users with distinct roles, such as admin and clerk, so the test harness has something meaningful to assert.
Annotating EJB methods with authorisation policies
The meat of declarative security lives in the session bean layer. Place @RolesAllowed on a class or method to restrict callers to a list of named roles, then add @DeclareRoles on the same class so the runtime knows which role names to look up.
A common pattern is a facade bean that exposes read methods as @PermitAll while limiting write operations to @RolesAllowed({"admin"}). For more sensitive flows, stack @DenyAll on a method that should never be invoked directly, forcing clients through a managed gateway instead.
Message-driven beans can carry @RunAs to elevate privileges during asynchronous processing, which is handy when a worker must call another protected resource without propagating the original caller identity.
Protecting the web layer with @ServletSecurity
Servlet 3.0 and later support @ServletSecurity on HttpServlet subclasses, and NetBeans recognises the annotations when generating code. Combine @HttpConstraint with @HttpMethodConstraint to spell out which HTTP verbs require authentication and which roles can call them.
For a JSON-style REST endpoint, mark the class with @RolesAllowed("api-client") and set rolesAllowed on individual methods only when the policy differs. This keeps the security intent close to the route, which makes audits easier when an ACSC-aligned review team walks through the codebase.
When you need to forward a caller's identity down into the EJB layer, read the principal from the HttpServletRequest or inject a SecurityContext via @Resource, depending on the container. NetBeans hints often flag unused injections during a code review, which can save an afternoon of confusion when something fails to deploy.
Verifying behaviour with JUnit and coverage reports
After annotations are in place, you need evidence that they actually fire. A small set of JUnit tests, executed through NetBeans, can call the protected methods directly and assert that access denied exceptions appear when expected.
Detailed instructions on running these tests with coverage reports inside the IDE are available in the coverage reports guide. Coverage data lets you see which annotated methods still lack a corresponding test, useful when chasing stray authorisation bugs during a code freeze.
Aim for one negative test per protected method, plus a happy path that exercises the permitted roles. Skipping negative cases is a common cause of access-control regressions that slip into production.
Choosing a runtime and avoiding common pitfalls
Different servers behave slightly differently around security annotations, and teams that previously relied on ejb-jar.xml and web.xml often forget that annotations and descriptors are merged at deploy time. A stale descriptor can quietly override the annotation policy, so audit your descriptors regularly, especially after a NetBeans upgrade that regenerates boilerplate.
Another trap is @RunAs, which elevates a method's privilege for its own execution but does not affect outbound calls without a corresponding identity propagation configuration. Test cross-module calls explicitly, including from a web tier into an EJB module in the same EAR.
The comparison below summarises practical points when picking a runtime, with a focus on options common in Australian teams.
| Server | Annotation support | Identity store options | Notes for Australian teams |
|---|---|---|---|
| GlassFish 7 | Full Jakarta EE 10 | File, JDBC, LDAP, custom | Bundled with NetBeans, easiest for local work |
| Payara 6 | Full Jakarta EE 10 | Same as GlassFish plus MicroProfile | Common on AU cloud VMs, good community support |
| WildFly 31 | Full Jakarta EE 10 | JDBC, LDAP, Elytron custom stores | Heavier footprint, useful for hybrid Windows/Linux shops |
Practical recommendations for annotation-based security
Annotation-based security works best when the team treats the security model as living code rather than a one-off configuration. The following habits keep the model readable, testable, and aligned with the codebase as it grows.
- Stick to a small, well-known set of role names and document them in a single file at the project root.
- Run a coverage report on every CI build and fail the build when annotated methods lack tests.
- Avoid mixing annotations and XML descriptors for the same policy; pick one as the source of truth.
- Mirror your production identity store in a local JDBC realm so developers see the same role resolution behaviour.
- Schedule a quarterly audit of roles declared in @DeclareRoles against the actual users seeded into the realm.
- Keep the application server version pinned across the team to avoid silent annotation drift.
For more enterprise Java guides and NetBeans tips, swing past NetBeans Blog.