Quantcast
Channel: Arjan Tijms' Weblog
Viewing all 76 articles
Browse latest View live

Java EE 7 server Liberty 9 beta 2016.1 tested for JASPIC support

$
0
0
IBM recently released the latest monthly beta of their modern and light weight Java EE 7 server; Liberty 9 beta 2016.1. Previous beta releases of Liberty 9 already performed quite well when it came to Java EE's portable authentication (JASPIC), but weren't perfect yet.

In this article we take a look to see if JASPIC support has improved in the latest release. To find out we executed the JASPIC tests against this latest release. For comparison the previous Liberty beta as well as the latest (snapshots) of Payara and WildFly are shown.

One thing to note is that previous downloads of recent Liberty betas were always for a full Java EE 7 server. For some inexplainable reason this month's beta is "only" a Java EE 7 web profile. Possibly this is a bug on the download page, as the size that as stated (116 mb) is not the same as the actual archive that's downloaded (94 mb).

One of Liberty's unique features is that it has a very elaborate and smooth system to install new components and their dependencies. In a way it's a bit like Maven dependency management but for the AS. With the help of this system the mysteriously missing Java EE 7 components could be installed after unpacking Liberty with the following command:


bin/installUtility install javaee-7.0
Additionally the so-called local connector was needed to run the tests. Previous betas included this as well, but it now had to be installed separately too:

bin/installUtility install localConnector-1.0

After this we could run the tests. The results are shown in the table below:

Running the Java EE 7 samples JASPIC tests
ModuleTestPayara 4.1.1.161-preWildFly 10rc5Liberty 9 beta 2016.1Liberty 9 beta 2015.11
async-authenticationtestBasicAsync
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedPageNotLoggedin
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedPageLoggedin
Passed
Passed
Passed
Passed
basic-authenticationtestPublicPageLoggedin
Passed
Passed
Passed
Passed
basic-authenticationtestPublicPageNotLoggedin
Passed
Passed
Passed
Passed
basic-authenticationtestPublicAccessIsStateless
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedAccessIsStateless
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedAccessIsStateless2
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedThenPublicAccessIsStateless
Passed
Passed
Passed
Passed
custom-principaltestProtectedPageLoggedin
Passed
Passed
Passed
Passed
custom-principaltestPublicPageLoggedin
Passed
Passed
Passed
Passed
custom-principaltestPublicAccessIsStateless
Passed
Passed
Passed
Passed
custom-principaltestProtectedAccessIsStateless
Passed
Passed
Passed
Passed
custom-principaltestProtectedAccessIsStateless2
Passed
Passed
Passed
Passed
custom-principaltestProtectedThenPublicAccessIsStateless
Passed
Passed
Passed
Passed
dispatchingtestBasicForwardViaProtectedResource
Passed
Passed
Passed
Passed
dispatchingtestBasicForwardViaPublicResource
Passed
Passed
Passed
Passed
dispatchingtestBasicIncludeViaPublicResource
Passed
Passed
Passed
Failure
dispatching-jsf-cditestCDIForwardViaProtectedResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestCDIForwardViaPublicResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestCDIIncludeViaPublicResource
Passed
Passed
Passed
Failure
dispatching-jsf-cditestJSFwithCDIForwardViaPublicResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestJSFwithCDIForwardViaProtectedResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestJSFwithCDIIncludeViaPublicResource
Failure
Failure
Failure
Failure
dispatching-jsf-cditestJSFForwardViaPublicResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestJSFForwardViaProtectedResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestJSFIncludeViaPublicResource
Failure
Failure
Failure
Failure
ejb-propagationpublicServletCallingProtectedEJB
Passed
Passed
Passed
Passed
ejb-propagationprotectedServletCallingProtectedEJB
Passed
Passed
Passed
Passed
ejb-propagationpublicServletCallingPublicEJBThenLogout
Passed
Passed
Passed
Passed
ejb-propagationprotectedServletCallingPublicEJB
Passed
Passed
Passed
Passed
invoke-ejb-cdiprotectedInvokeCDIFromSecureResponse
Passed
Passed
Failure
Failure
invoke-ejb-cdiprotectedInvokeCDIFromCleanSubject
Passed
Passed
Passed
Passed
invoke-ejb-cdiprotectedInvokeCDIFromValidateRequest
Passed
Passed
Failure
Failure
invoke-ejb-cdipublicInvokeCDIFromSecureResponse
Passed
Passed
Failure
Failure
invoke-ejb-cdipublicInvokeCDIFromValidateRequest
Passed
Passed
Failure
Failure
invoke-ejb-cdipublicInvokeCDIFromCleanSubject
Passed
Passed
Passed
Failure
invoke-ejb-cdiprotectedInvokeEJBFromSecureResponse
Passed
Passed
Passed
Passed
invoke-ejb-cdiprotectedInvokeEJBFromCleanSubject
Passed
Passed
Passed
Passed
invoke-ejb-cdiprotectedInvokeEJBFromValidateRequest
Passed
Passed
Passed
Passed
invoke-ejb-cdipublicInvokeEJBFromSecureResponse
Passed
Passed
Passed
Passed
invoke-ejb-cdipublicInvokeEJBFromValidateRequest
Passed
Passed
Passed
Passed
invoke-ejb-cdipublicInvokeEJBFromCleanSubject
Passed
Passed
Passed
Passed
jacc-propagationcallingJACCWhenAuthenticated
Passed
Failure
Failure
Failure
jacc-propagationcallingJACCWhenAuthenticated
Passed
Failure
Failure
Failure
jacc-propagationcallingJACCWhenNotAuthenticated
Passed
Passed
Failure
Failure
lifecycletestBasicSAMMethodsCalled
Passed
Passed
Passed
Passed
lifecycletestLogout
Passed
Passed
Passed
Passed
register-sessiontestJoinSessionIsOptional
Passed
Passed
Passed
Passed
register-sessiontestRemembersSession
Passed
Passed
Passed
Passed
status-codestest404inResponse
Passed
Passed
Passed
Passed
status-codestest404inResponse
Passed
Passed
Passed
Passed
wrappingtestResponseWrapping
Passed
Passed
Passed
Passed
wrappingtestRequestWrapping
Passed
Passed
Passed
Passed

As can be seen Liberty's JASPIC support has again improved. Including a resource (e.g. Servlet or JSP) into the response now generally works again. Only JSF based includes are still broken, but this is likely not a Liberty problem but a JSF one.

Additionally one CDI problem was fixed; obtaining and invoking a CDI bean from a SAM's cleanSubject method. This already worked on previous betas when the request was to a protected resource, but mysteriously failed for public resources. The cleanSubject method is generally somewhat easier to support, as this method is called in response to HttpServletRequest#logout and thus happens during the so-called resource invocation (i.e. from the context of a Servlet where CDI already is mandated to be available).

The real challenge for JASPIC implementors is to make sure that CDI works before and after this resource invocation. Payara, GlassFish and JBoss/WildFly have succeeded in supporting this, but Liberty not yet. This support is particularly important since the upcoming Java EE Security API (JSR 375) completely depends on the ability to obtain and invoke CDI beans from the validateRequest and secureResponse methods. Unfortunately early versions of the JSR 375 API can now not be tested on Liberty.

Conclusion

Liberty is improving rapidly and already very useful to deploy portable Java EE 7 authentication modules on. Hopefully it will soon take one the last hurdles and provide full support for CDI as well.

Arjan Tijms


Servlet 4.0's mapping API previewed in Tomcat 9.0 m4

$
0
0
Without doubt one of the most important Servlet implementations is done by Tomcat. Tomcat serves, or has served, as the base for Servlet functionality in a number of Java EE application servers and is one of the most frequently used standalone Servlet containers.

Contrary to what is often thought, Tomcat is not the reference implementation for Servlet; the build-in Servlet container of GlassFish is. Even though important parts of that GlassFish Servlet implementation are in fact based on Tomcat it's a different code base. Normally GlassFish being the RI implements new spec level functionality first, but unfortunately during the Java EE 8/Servlet 4.0 cycle the GlassFish team is working on other assignments and hasn't worked out a schedule to incorporate this new functionality.

Luckily Tomcat has taken the initiative and in Tomcat 9.0.0.M4 the proposed Servlet 4.0 Mapping API has been implemented.

This API allows Servlet users to find out via which mapping a Servlet was being called. E.g. a Servlet can be mapped by a user to both "/foo/*" and "*.bar" among others. Especially for frameworks it can be important to know what the mapping was, since not rarely something (typically a template file) has to be loaded based on what the * from the above example was. And not only that, if links have to be generated they often need to use the same mapping that was used to call the Servlet.

The current way to do this is a little hairy and therefor quite error prone; it requires checking against the many components of the request URI. The new proposed API greatly simplifies this via the new HttpServletRequest#getMapping() method:


public default Mapping getMapping() {
// ...
}
The new Mapping type that can be seen in the signature of the above method looks as follows:

/**
* Represents how the request from which this object was obtained was mapped to
* the associated servlet.
*
* @since 4.0
*/
public interface Mapping {

/**
* @return The value that was matched or the empty String if not known.
*/
String getMatchValue();

/**
* @return The {@code url-pattern} that matched this request or the empty
* String if not known.
*/
String getPattern();

/**
* @return The type of match ({@link MappingMatch#UNKNOWN} if not known)
*/
MappingMatch getMatchType();
}
The MappingMatch is an enumeration of the different types of possible mappings as shown below:

/**
* Represents the ways that a request can be mapped to a servlet
*
* @since 4.0
*/
public enum MappingMatch {

CONTEXT_ROOT,
DEFAULT,
EXACT,
EXTENSION,
IMPLICIT,
PATH,
UNKNOWN
}
To test out the new functionality the following test Servlet was used:

@WebServlet({"/path/*", "*.ext", "", "/", "/exact"})
public class Servlet extends HttpServlet {

private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

Mapping mapping = request.getMapping();

response.getWriter()
.append("Mapping match:")
.append(mapping.getMatchType().name())
.append("\n")
.append("Match value:")
.append(mapping.getMatchValue())
.append("\n")
.append("Pattern:")
.append(mapping.getPattern());
}

}

As can be seen this Servlet is mapped via a path mapping ("/path/*"), extension mapping ("*.ext"), context root mapping (""), default mapping ("/") and a single exact mapping ("/exact"). We deployed this Servlet via an application called "servlet4" to a Tomcat 9.0 M4 instance and subjected it to a couple of requests via a browser. The results are shown below:

Path mapping
http://localhost:8080/servlet4/path/foo


Mapping match:PATH
Match value:/foo
Pattern:/path/*

Extension mapping
http://localhost:8080/servlet4/foo.ext


Mapping match:EXTENSION
Match value:/foo
Pattern:*.ext

Context root mapping
http://localhost:8080/servlet4


Mapping match:CONTEXT_ROOT
Match value:
Pattern:

Default (fallback) mapping
http://localhost:8080/servlet4/doesnotexist


Mapping match:DEFAULT
Match value:/
Pattern:/

Exact mapping
http://localhost:8080/servlet4/exact


Mapping match:EXACT
Match value:/exact
Pattern:/exact
To test the implicit mapping (as per Servlet spec 12.2.1), the following JSP file was used:

<%
Mapping mapping = request.getMapping();

response.getWriter()
.append("Mapping match:")
.append(mapping.getMatchType().name())
.append("\n")
.append("Match value:")
.append(mapping.getMatchValue())
.append("\n")
.append("Pattern:")
.append(mapping.getPattern());
%>
This was however seen by Tomcat as a regular extension mapping:

Implicit mapping
http://localhost:8080/servlet4/page.jsp


Mapping match:EXTENSION
Match value:/page
Pattern:*.jsp
Implicit mappings are a little bit difficult to represent. Are they a mapping themselves, or is it just extra information? I.e. can you speak of an "implicit extension mapping" and an "implicit path mapping"?

Conclusion

At the moment it's unfortunately difficult to commit code to the Servlet RI (GlassFish), but Tomcat 9.0 M4 can be used to get an early glimpse of one of the new Servlet APIs. As the examples have shown, the new Mapping API now makes it trivial to find out via which mapping a Servlet was selected. The "implicit" mapping type however may still need some discussion.

Arjan Tijms

Java EE's mysterious message policy

$
0
0
Users of Java EE authentication (JASPIC) may have noticed that the initialize method of a SAM takes two parameters of type MessagePolicy. But what are these parameters used for? In this article we'll take a somewhat deeper look.

In practice, the overwhelming majority of SAMs only seem to use this MessagePolicy in one way; completely ignore it. As such, there aren't many if any examples available that demonstrate how these passed in policies should actually be enforced.

The JASPIC spec isn't quite clear about this either. It does seem to say in a somewhat cryptic way that the isMandatory method is an alias for the "javax.security.auth.message.MessagePolicy.isMandatory" entry in the MessageInfo map, and that the ProtectionPolicy of the TargetPolicy of the MessagePolicy must be ProtectionPolicy.AUTHENTICATE_SENDER and/or ProtectionPolicy.AUTHENTICATE_CONTENT.

Pretty much the only example we have in code that at least references the MessagePolicy type is within the Java EE reference implementation; GlassFish. Although GlassFish doesn't use JASPIC for the Servlet defined authentication mechanisms (FORM, BASIC, ...), it does uses JASPIC for the authentication mechanism protecting its build-in admin console. This is configured in domain.xml as follows:


<message-security-config auth-layer="HttpServlet">
<provider-config provider-type="server"
provider-id="GFConsoleAuthModule"
class-name="org.glassfish.admingui.common.security.AdminConsoleAuthModule">
<request-policy auth-source="sender"/&gt
<response-policy/&gt
<property name="loginPage" value="/login.jsf"/&gt
<property name="loginErrorPage" value="/loginError.jsf"/&gt
</provider-config>
</message-security-config>

Unfortunately, despite a minimal request policy being configured here, the actual implementation of AdminConsoleAuthModule does the same thing that basically all other SAMs do: ignore it.

For another potential hint, let's see what the RI actually does internally with the message policy before it passes it to a SAM. For this I started at the entry point of a SAM, when the runtime calls the validateRequest method of the encapsulating context. In order to make things readable for this article, I removed all alternative branches in the code (mostly permutations of client/server modules and new/old modules (new = jaspic, old = the GlassFish proprietary predecessor of JASPIC) and Servlet/SOAP). With those branches removed and flattening the code found in many helper methods and contained objects, it looks as follows:


// Check if the resource is secured and put as string in Map
isMandatory = !webSecMgr.permitAll(req);
if (isMandatory || calledFromAuthenticate) {
messageInfo.getMap().put(IS_MANDATORY, TRUE.toString());
}

// Get “true” / “false” string from map, convert it to Boolean and then to string again
String isMandatoryStr = messageInfo.getMap().get(IS_MANDATORY);
String authContextID = Boolean.valueOf(isMandatoryStr).toString();

// Convert once again to Boolean, and set to MANDATORY or OPTIONAL policy
messagePolicy = Boolean.valueOf(authContextID)?
new MessagePolicy[] { MANDATORY_POLICY, null } : // response policy always null
new MessagePolicy[] { OPTIONAL_POLICY, null }

IDEntry idEntry = configMap.get(“HttpServlet”).idMap.get(providerID);

// Set the definite request policy, but messagePolicy[0] is never null here
// for the “HttpServlet” layer
MessagePolicy requestPolicy = (messagePolicy[0] != null || messagePolicy[1] != null)?
messagePolicy[0] : // will always be chosen here
idEntry.requestPolicy; // the policy as parsed from domain.xml, always unused

Entry entry = new Entry(idEntry.moduleClassName, requestPolicy, idEntry.options);

// Pass the message policies into the SAM instance
ServerAuthModule sam = entry.newInstance();
sam.initialize(
entry.getRequestPolicy(),
entry.getResponsePolicy(), handler, map);

ModuleInfo moduleInfo = ModuleInfo(sam, map);

ServerAuthModule moduleObj = moduleInfo.getModule();
Map moduleMap = moduleInfo.getMap();

ServerAuthContext serverAuthContext = new GFServerAuthContext(moduleObj, moduleMap);

// Invoke the context, which on its turn will invoke the SAM we just initialized
AuthStatus authStatus = serverAuthContext.validateRequest(messageInfo, subject, null);

As can be seen, despite there being a path for setting the parsed request policy from domain.xml (the idEntry.requestPolicy), the code always chooses between one of two fixed policies; MANDATORY_POLICY or OPTIONAL_POLICY, depending on the same IS_MANDATORY value ("javax.security.auth.message.MessagePolicy.isMandatory") that is put in the message info map.

Those two fixed policies are set as static final variables as follows:


private static final MessagePolicy MANDATORY_POLICY =
getMessagePolicy(true);

private static final MessagePolicy OPTIONAL_POLICY =
getMessagePolicy(false);
Where the getMessagePolicy() method has the following relevant content (code branches that were never taken have been cut out again):

public static MessagePolicy getMessagePolicy (boolean mandatory) {

List<TargetPolicy> targetPolicies = new ArrayList<TargetPolicy>();

targetPolicies.add(new TargetPolicy(
null, // No Target
new ProtectionPolicy() {
public String getID() {
return ProtectionPolicy.AUTHENTICATE_SENDER;
}
})
);

return new MessagePolicy(
targetPolicies.toArray(new TargetPolicy[targetPolicies.size()]),
mandatory);
}

Conclusion

The conclusion seems to be, assuming that the RI code is as spec compliant as we can get, that MessagePolicy#isMandatory() is just an alternative for checking the message info map, while the TargetPolicy, Target and ProtectionPolicy are essentially useless for a Servlet Container Profile SAM, since at least for the RI they always have the same constant value. It has to be noted that if a SAM is registered programmatically, the entire initialization of the SAM is under the application's control and the behavior of the server doesn't apply.

Speculating, it might be the case that AUTHENTICATE_SENDER simply means "do what a SAM is supposed to do in validateRequest()" (e.g. authenticating callers), while the potential alternative or additional AUTHENTICATE_CONTENT means "do what a SAM is supposed to do in secureResponse()" (e.g. encrypting the response). If that interpretation would indeed be correct, one may see these message policies as standard switches (properties) for these two methods. E.g. a message policy with AUTHENTICATE_CONTENT and isMandatory() returning true would then mean that the SAM *must* encrypt the response. This latter thing however seems to be just as rare in practice as actually looking at the message policy is.

A quick glimpse at the SOAP Profile, and some of the implementation code in the RI, revealed that the entire message policy concept may have some more use over there. As JASPIC was originally designed with many potential other profiles in mind (e.g. for EJB, JMS, etc), it could also well be that the concept was designed for a future that just never came to be.

Arjan Tijms

The state of portable authentication in Java EE, mid 2016 update

$
0
0
In the beginning of this year and two months prior to that we looked at how well modern Java EE servers supported portable authentication (JASPIC) in Java EE. In this article we look at the current state of the union.

Originally the situation didn't looked that rosy, but since then things have been steadily improving. Since last time new versions of Payara, WildFly and Liberty have been released, while TomEE now also supports JASPIC. No new versions of Oracle's WebLogic and GlassFish were released. New tests have been added for registering a session with a custom principal and EJB propagation after register session.

The results of running the latest series of JASPIC tests are shown below:

Running the Java EE 7 samples JASPIC tests
ModuleTestPayara 4.1.1.163 snapshotWildFly 10.0.0Liberty 9 beta 2016.5TomEE 7.0.0
async-authenticationtestBasicAsync
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedPageNotLoggedin
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedPageLoggedin
Passed
Passed
Passed
Passed
basic-authenticationtestPublicPageLoggedin
Passed
Passed
Passed
Passed
basic-authenticationtestPublicPageNotLoggedin
Passed
Passed
Passed
Passed
basic-authenticationtestPublicAccessIsStateless
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedAccessIsStateless
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedAccessIsStateless2
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedThenPublicAccessIsStateless
Passed
Passed
Passed
Passed
custom-principaltestProtectedPageLoggedin
Passed
Passed
Passed
Passed
custom-principaltestPublicPageLoggedin
Passed
Passed
Passed
Passed
custom-principaltestPublicAccessIsStateless
Passed
Passed
Passed
Passed
custom-principaltestProtectedAccessIsStateless
Passed
Passed
Passed
Passed
custom-principaltestProtectedAccessIsStateless2
Passed
Passed
Passed
Passed
custom-principaltestProtectedThenPublicAccessIsStateless
Passed
Passed
Passed
Passed
dispatchingtestBasicForwardViaProtectedResource
Passed
Passed
Passed
Passed
dispatchingtestBasicForwardViaPublicResource
Passed
Passed
Passed
Passed
dispatchingtestBasicIncludeViaPublicResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestCDIForwardViaProtectedResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestCDIForwardViaPublicResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestCDIIncludeViaPublicResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestJSFwithCDIForwardViaPublicResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestJSFwithCDIForwardViaProtectedResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestJSFwithCDIIncludeViaPublicResource
Failure
Failure
Failure
Passed
dispatching-jsf-cditestJSFForwardViaPublicResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestJSFForwardViaProtectedResource
Passed
Passed
Passed
Passed
dispatching-jsf-cditestJSFIncludeViaPublicResource
Failure
Failure
Failure
Passed
ejb-propagationpublicServletCallingProtectedEJB
Passed
Passed
Passed
Passed
ejb-propagationprotectedServletCallingProtectedEJB
Passed
Passed
Passed
Passed
ejb-propagationpublicServletCallingPublicEJBThenLogout
Passed
Passed
Passed
Passed
ejb-propagationprotectedServletCallingPublicEJB
Passed
Passed
Passed
Passed
invoke-ejb-cdiprotectedInvokeCDIFromSecureResponse
Passed
Passed
Failure
Passed
invoke-ejb-cdiprotectedInvokeCDIFromCleanSubject
Passed
Passed
Passed
Passed
invoke-ejb-cdiprotectedInvokeCDIFromValidateRequest
Passed
Passed
Failure
Passed
invoke-ejb-cdipublicInvokeCDIFromSecureResponse
Passed
Passed
Failure
Passed
invoke-ejb-cdipublicInvokeCDIFromValidateRequest
Passed
Passed
Failure
Passed
invoke-ejb-cdipublicInvokeCDIFromCleanSubject
Passed
Passed
Passed
Passed
invoke-ejb-cdiprotectedInvokeEJBFromSecureResponse
Passed
Passed
Passed
Passed
invoke-ejb-cdiprotectedInvokeEJBFromCleanSubject
Passed
Passed
Passed
Passed
invoke-ejb-cdiprotectedInvokeEJBFromValidateRequest
Passed
Passed
Passed
Passed
invoke-ejb-cdipublicInvokeEJBFromSecureResponse
Passed
Passed
Passed
Passed
invoke-ejb-cdipublicInvokeEJBFromValidateRequest
Passed
Passed
Passed
Passed
invoke-ejb-cdipublicInvokeEJBFromCleanSubject
Passed
Passed
Passed
Passed
jacc-propagationcallingJACCWhenAuthenticated
Passed
Failure
Failure
Failure
jacc-propagationcallingJACCWhenAuthenticated
Passed
Failure
Failure
Failure
jacc-propagationcallingJACCWhenNotAuthenticated
Passed
Passed
Failure
Failure
lifecycletestBasicSAMMethodsCalled
Passed
Passed
Passed
Passed
lifecycletestLogout
Passed
Passed
Passed
Passed
register-sessiontestRemembersSessionEJB
Passed
Failure
Passed
Passed
register-sessiontestJoinSessionIsOptional
Passed
Passed
Failure
Passed
register-sessiontestRemembersSession
Passed
Passed
Passed
Passed
register-sessiontestRemembersSessionEJB
Passed
Failure
Passed
Passed
register-sessiontestJoinSessionIsOptional
Passed
Passed
Failure
Passed
register-sessiontestRemembersSession
Passed
Passed
Passed
Passed
status-codestest404inResponse
Passed
Passed
Passed
Passed
status-codestest404inResponse
Passed
Passed
Passed
Passed
wrappingtestResponseWrapping
Passed
Passed
Passed
Passed
wrappingtestRequestWrapping
Passed
Passed
Passed
Passed

Not directly shown in the table, but one of the biggest changes is that Liberty 9 beta 2016.5 no longer needs JASPIC to be activated in a problematic and proprietary way. Historically Liberty was one of the most problematic servers in this area. It originally required all users and groups to be made known to a Liberty specific artefact called a user registry (a kind of identity store). This requirement was later relaxed such that only groups had to be defined, but since group to role mapping was also mandatory, this stil meant defining the same group at least 3 times if no actual group mapping was needed.

In Liberty 9 beta 2016.5 all this overhead is now completely gone, and just like GlassFish and WebLogic, JASPIC just works without any activation whatsoever (with a caveat for GlassFish that by default it does require group to role mapping). One thing to watch out for is that if you do need group to role mapping, you seemingly can't just use Liberty's role mapping file (ibm-application-bnd.xml), but also need to define the above mentioned user registry again. All other servers (that feature a role mapper) allow the mapping of groups set by a JASPIC SAM via only a single XML file. When asked about this, the Liberty lead mentioned that this is due to backwards compatibility, which does make sense. It's also not such a bad thing; if you want to use the proprietary group to role mapping feature it's only a relatively small extra step to also activate a proprietary artefact such as the user registry.

As far as JASPIC functionality goes, Liberty keeps failing the CDI related tests and the JACC ones. The JACC ones are a clear spec violation (confirmed by the JACC and JASPIC spec lead), but since it concerns a requirement that was never enforced (namely, JACC has to be available and used by default) it's likely far from trivial to just fix this. Liberty also fails a test where the authenticated user is changed during the same HTTP session. This however clashes with Liberty's protection against a session fixation attack, which for instance happens when a user logs out and without resetting the http session (specifically changing its ID) a new user logs in again. This protection can be disabled by putting <httpSession securityIntegrationEnabled="false"/&gt in server.xml.

As mentioned above, TomEE is new to JASPIC scene, but what an entrance it makes! In it's very first release it passed all JASPIC tests, safe the JACC ones. TomEE (as not a full Java EE 7 certified server) is however not required to support JACC at all, let alone out of the box. Since TomEE does actually support JACC it may be possible to have it pass these tests as well. Right from the start TomEE also doesn't require any explicit activation of JASPIC. It just works out of the box.

JBoss/WildFly, while still having a very good JASPIC implementation fell a tiny bit behind. It still doesn't pass all JACC tests, even though JACC is in fact available by default (a bug prevents roles to be propagated correctly). Additionally, a new bug was found that prevents roles being propagated to EJB beans when the remember session feature is used. JBoss also still requires the dummy-like marker file (jboss-web.xml) in an archive to activate JASPIC. Even though such marker file is only a small nuisance compared to having to modify the server itself, it does make JBoss the sole server now that requires such activation at all (but as mentioned above, GlassFish/Payara requires a proprietary group to role mapping file to be present).

Payara also suffered from a newly discovered bug, this one involving the combination of the remember session feature and a custom principal. This was however quickly fixed in the 4.1.1.163 branch and Payara remains one of the strongest JASPIC implementations. There's essentially only one minor failure involving a not too common case of including a JSF resource from within a SAM.

Conclusion

7 years after portable authentication was introduced in Java EE 6 and 3 years after its revision in Java EE 7, JASPIC implementations are now finally getting really compliant. There's a residu of bugs in the various implementations that still need to be fixed, and a few inconveniences to take away in some servers (JBoss' jboss-web.xml and GlassFish/Payara's glassfish-web.xml), but overal things are starting to look very good.

The one big exception remains WebLogic 12.2.1, which currently doesn't work at all after a major bug was introduced in that version that prevents basic authentication to work correctly (effectively a blocker bug that makes running all other tests rather moot)

Arjan Tijms

Simplified custom authorization rules in Java EE

$
0
0
In a previous article we looked at implementing a Java EE authorization module using the JACC specification. This module implemented the default authorization rules as specified by the JACC-, Servlet- and EJB specifications. In this article we go beyond that default algorithm and take a look at providing our own custom authorization rules.

In order to implement custom rules, one would traditionally ship an entire JACC provider with factory, configuration and policy. Not only is this a lot of code (JACC doesn't have any code that can be reused, for the smallest change everything needs to be implemented from scratch), it's also problematic that a JACC provider is global for the entire application server, while authorization rules are almost always specific for an individual application. Even when you adhere to the best practice of using one application per server, it's still quite a hassle to re-install the JACC provider after every little change separately from the application.

For this article we're therefor going to employ a different approach; use CDI to delegate from a single JACC provider that's installed once, to an application specific CDI bean. Incidentally this is largely the same thing Soteria/JSR 375 is doing for authentication mechanisms, which the key difference that the Java EE authentication SPI -does- allow authentication modules to be installed per application.

For the actual custom authorization rule we took inspiration from a rather interesting question and answer on StackOverflow:

Is it possible to determine group membership of a user on demand instead of when logging in via a ServerAuthModule (JASPIC)?

As it appears, the answer to this question is yes ;)

In order to come to a solution for the above stated problem we first took the original JACC provider from the previous article and refactored it a little. The permissions that were previously put in the intermediate base class TestPolicyConfigurationPermissions were factored out to a separate struct like class:


public class SecurityConstraints {

private Permissions excludedPermissions = new Permissions();
private Permissions uncheckedPermissions = new Permissions();
private Map<String, Permissions> perRolePermissions = new HashMap<String, Permissions>();

// + getters/setters
Furthermore a new class was introduced that holds the caller (name) principal, the (mapped) roles and the raw set of unmapped principals (which are often server specific):

public class Caller {

private Principal callerPrincipal;
private List<String> roles;
private List<Principal> unmappedPrincipals;

// + getters/setters
Next we define an interface for the application to implement. Our JACC provider will call this at certain points during the authorization process:

public interface AuthorizationMechanism {

default Boolean preAuthenticatePreAuthorize(Permission requestedPermission, SecurityConstraints securityConstraints) {
return null;
}

default Boolean preAuthenticatePreAuthorizeByRole(Permission requestedPermission, SecurityConstraints securityConstraints) {
return null;
}

default Boolean postAuthenticatePreAuthorize(Permission requestedPermission, Caller caller, SecurityConstraints securityConstraints) {
return null;
}

default Boolean postAuthenticatePreAuthorizeByRole(Permission requestedPermission, Caller caller, SecurityConstraints securityConstraints) {
return null;
}
}
As can be seen we distinguish for authorization decisions before authentication has taken place and thereafter, and for those at the start of an authorization decision and right before it comes time to check for role based permissions. The difference between those last two moments is that for the latter the tests for excluded permissions (those granted to no one) and unchecked (permissions granted to everyone) have already been performed. (Note that methods have been used for now, but perhaps events are the better solution here)

With these artefacts in place we can now modify the JACC Policy class to request a bean via CDI that implements the AuthorizationMechanism interface, and if it exists call one of the appropriate methods. The following shows an excerpt of this:


boolean postAuthenticate = domain.getPrincipals().length > 0;

AuthorizationMechanism mechanism = getBeanReferenceExtra(AuthorizationMechanism.class);
Caller caller = null;

if (postAuthenticate) {
caller = new Caller(
roleMapper.getCallerPrincipalFromPrincipals(currentUserPrincipals),
roleMapper.getMappedRolesFromPrincipals(currentUserPrincipals),
currentUserPrincipals);
}

if (mechanism != null) {
Boolean authorizationOutcome = postAuthenticate?
mechanism.postAuthenticatePreAuthorize(requestedPermission, caller, securityConstraints) :
mechanism.preAuthenticatePreAuthorize(requestedPermission, securityConstraints);

if (authorizationOutcome != null) {
return authorizationOutcome;
}
}

In the code above getBeanReferenceExtra uses CDI to fetch a bean of type AuthorizationMechanism. This method works around a bug in Payara where the so-called component namespaces aren't being set. This bug is pretty much the same as also existed for calling a JASPIC SAM. If the mechanism is not null, then depending on whether authentication has already happened or not either the postAuthenticatePreAuthorize or the preAuthenticatePreAuthorize is called.

The JACC Policy doesn't tell us explicitly if the call is before or after authentication, but we can deduct this by looking at the passed-in principals. The assumption is that before authentication there are no principals at all, and after authentication there's at least one (if there was no actual authentication being done, the so-called "unauthenticated caller principal" is added).

For further details see the full source code.

With the JACC provider in place we can now create a Java EE web application that takes advantage of it. We'll start with a custom JSR 375 IdentityStore that only authenticates a single user named "test" and doesn't return any groups:


@RequestScoped
public class CustomIdentityStore implements IdentityStore {

public CredentialValidationResult validate(UsernamePasswordCredential usernamePasswordCredential) {

if (usernamePasswordCredential.getCaller().equals("test") &&
usernamePasswordCredential.getPassword().compareTo("secret1")) {

return new CredentialValidationResult(
new CallerPrincipal("test"),
null // no static groups, dynamically handled via authorization mechanism
);
}

return INVALID_RESULT;
}

}
We also add a custom JSR 375 HttpAuthenticationMechanism, one that's just used for testing purposes:

@RequestScoped
public class CustomAuthenticationMechanism implements HttpAuthenticationMechanism {

@Inject
private IdentityStore identityStore;

@Override
public AuthStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) throws AuthException {

if (request.getParameter("name") != null && request.getParameter("password") != null) {

CredentialValidationResult result = identityStore.validate(
new UsernamePasswordCredential(request.getParameter("name"), request.getParameter("password")));

if (result.getStatus() == VALID) {
return httpMessageContext.notifyContainerAboutLogin(
result.getCallerPrincipal(), result.getCallerGroups());
} else {
throw new AuthException("Login failed");
}
}

return httpMessageContext.doNothing();
}

}
Note that we could have omitted both the custom identity store and custom authentication mechanism and instead configured the default embedded store and the default BASIC authentication mechanism, but now we more clearly see what's exactly happening in the authentication process. Also note that the HttpAuthenticationMechanism is a CDI based HTTP specific variant of the ServerAuthModule that was mentioned in the SO question cited above.

Let's now finally look at our custom authorization rule, which basically looks as follows:


@ApplicationScoped
public class CustomAuthorizationMechanism implements AuthorizationMechanism {

@Override
public Boolean postAuthenticatePreAuthorizeByRole(Permission requestedPermission, Caller caller, SecurityConstraints securityConstraints) {

return getRequiredRoles(securityConstraints.getPerRolePermissions(), requestedPermission)
.stream()
.anyMatch(role -> isInRole(caller.getCallerPrincipal().getName(), role));
}
}
What's happening here is that our custom code is being asked to authorize the caller for some requested permission. Such permission can e.g. be a WebResourcePermission for a given protected path like /foo/bar.

In order to do the on demand membership check as was asked for in the SO question we start with using the getRequiredRoles method and the collectedSecurityConstraints to obtain a list of roles that are required for the requested permission. We then look if the current caller is in any of those roles using the isInRole method. This method can do whatever backend lookup is needed, but for an example application we'll mock it using a simple map where we put caller "test" in roles "foo", "bar" and "kaz".

For completeness, the getRequiredRoles method gets the roles that are required for a requested permission as follows:


return perRolePermissions
.entrySet().stream()
.filter(entry -> entry.getValue().implies(requestedPermission))
.map(e -> e.getKey())
.collect(toList());
In order to test if the authorization rule works we add a protected Servlet as follows:

@DeclareRoles({ "foo", "bar", "kaz" })
@WebServlet("/protected/servlet")
@ServletSecurity(@HttpConstraint(rolesAllowed = "foo"))
public class ProtectedServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.getWriter().write("This is a protected servlet \n");

String webName = null;
if (request.getUserPrincipal() != null) {
webName = request.getUserPrincipal().getName();
}

response.getWriter().write("web username: " + webName + "\n");

response.getWriter().write("web user has role \"foo\": " + request.isUserInRole("foo") + "\n");
response.getWriter().write("web user has role \"bar\": " + request.isUserInRole("bar") + "\n");
response.getWriter().write("web user has role \"kaz\": " + request.isUserInRole("kaz") + "\n");
}

}
The Servlet shown here is protected by the role "foo", so with the above given IdentityStore which doesn't return any groups/roles for our caller "test", we would normally not be able to access this Servlet. Yet, with the custom authorization rule in place we're able to access this Servlet just fine when authenticating as user "test".

Next we added a preAuthenticatePreAuthorize method to our authorization mechanism with some logging and also added logging to our existing postAuthenticatePreAuthorizeByRole method. We then deployed the application as "custom-authorization" to Payara 4.1.1.162 and requested http://localhost:8080/custom-authorization/protected/servlet?name=test&password=secret1. This resulted in the following log entries:


preAuthenticatePreAuthorize called. Requested permission: ("javax.security.jacc.WebUserDataPermission""/protected/servlet""GET")
preAuthenticatePreAuthorize called. Requested permission: ("javax.security.jacc.WebResourcePermission""/protected/servlet""GET")

validateRequest called. Authentication mandatory: true

postAuthenticatePreAuthorizeByRole called. Requested permission: ("javax.security.jacc.WebResourcePermission""/protected/servlet""GET")

postAuthenticatePreAuthorizeByRole called. Requested permission: ("javax.security.jacc.WebRoleRefPermission""org.omnifaces.authorization.ProtectedServlet""foo")
postAuthenticatePreAuthorizeByRole called. Requested permission: ("javax.security.jacc.WebRoleRefPermission""org.omnifaces.authorization.ProtectedServlet""bar")
postAuthenticatePreAuthorizeByRole called. Requested permission: ("javax.security.jacc.WebRoleRefPermission""org.omnifaces.authorization.ProtectedServlet""kaz")
What we see happening here is that our authorization mechanism is initially called twice before authentication. First to see if the request can be aborted early by checking if the protocol (http/https) is allowed, and secondly to see if the resource is allowed to be accessed publicly. If the resource is allowed to be accessed publicly, authentication is still being asked for, but it's not mandatory then.

For the request to "/protected/servlet" authentication is mandatory as shown above. Since authentication is thus mandatory, our authorization mechanism is called again after authentication for the same requested WebResourcePermission permission, but this time the caller data corresponding to the authenticated identity is also available. Our method will return "true" here, since ("javax.security.jacc.WebResourcePermission""/protected/servlet""GET") will turn out to require the role "foo", and our mock "isInRole" method will return "true" for caller "test" and role "foo".

We therefor continue to our requested resource, which means the servlet will be invoked.

Interesting to note here is that HttpServletRequest#isUserInRole is not implemented internally by checking a simple list of roles, but by calling our authorization module with a requested permission ("javax.security.jacc.WebRoleRefPermission""org.omnifaces.authorization.ProtectedServlet""[role name]"). The three isUserInRole calls that the servlet shown above does therefor show up in the log as three calls to our authorization mechanism, each for a different role.

Also interesting to note is that our authorization mechanism handles a requested permission to access "/protected/servlet" and a requested permission for isUserInRole("foo") completely identical. If necessary the authorization mechanism can of course inspect the requested permission, but for this use case that wasn't necessary.

To contrast the call to the protected servlet, let's also take a quick look at the log entries resulting from a call to a public servlet that's otherwise identical to the protected one:


preAuthenticatePreAuthorize called. Requested permission: ("javax.security.jacc.WebUserDataPermission""/public/servlet""GET")
preAuthenticatePreAuthorize called. Requested permission: ("javax.security.jacc.WebResourcePermission""/public/servlet""GET")

validateRequest called. Authentication mandatory: false

postAuthenticatePreAuthorizeByRole called. Requested permission: ("javax.security.jacc.WebRoleRefPermission""org.omnifaces.authorization.PublicServlet""foo")
postAuthenticatePreAuthorizeByRole called. Requested permission: ("javax.security.jacc.WebRoleRefPermission""org.omnifaces.authorization.PublicServlet""bar")
postAuthenticatePreAuthorizeByRole called. Requested permission: ("javax.security.jacc.WebRoleRefPermission""org.omnifaces.authorization.PublicServlet""kaz")
What we see here is that our authorization mechanism is initially called twice again, but since the default authorization algorithm will grant access to the anonymous caller the subsequent authentication is not mandatory and our authorization mechanism will also not be called a second time for the same resource permission.

For more details see the full source code of the example application.

Conclusion

We've seen that custom authorization rules allow us to do things that are normally not thought possible using Java EE security. Java EE's security model is clearly much more advanced than just the basic ability to check for roles, but much of its power has likely been untapped by many.

The reason for this is the relative obscurity of the JACC specification, the difficulty to install a provider and the very large amount of work required for even the smallest amount of custom authorization logic. The approach presented in this article allows us to re-use an existing JACC provider and provide custom authorization logic with a minimal amount of code.

What we presented here is only a prototype, but it may serve as a basis for authorization in the Java EE Security API (JSR 375).

Arjan Tijms

Custom authorization rules on IBM Liberty

$
0
0
Last month we presented a way how a Java EE application can provide custom rules for authorization. The code shown in that article was developed and tested using Payara. We're now going to look at how the code can be used on some other servers, starting with IBM's Liberty.

Liberty has a highly modularised architecture and features a rather amazing way by which and end user can compose the runtime. By means of its server.xml file, a Liberty user can add or remove nearly every individual feature that Liberty has independently. The Liberty core system keeps track of the dependencies of each module representing such feature and adds or removes its dependencies accordingly (in a way not quite unlike what a tool like Maven does at build time).

All this power does come at some price. For Liberty the JACC provider which is needed to implement the logic behind the custom authorization rules has to be turned into a Liberty specific module (called a user feature), which is quite a bit more work than needed for other servers (even the ones that are also modular).

Summarised we have to:

  • Create an OSGi bundle
  • Add our JACC provider jar to this bundle
  • Implement a Liberty specific service that returns the policy and factory instances from our provider
  • Make sure we have the right imports and exports
  • Create a Liberty Feature that references the previously created bundle and provides the right exports
  • Installing the feature in Liberty

IBM provides documentation on how to install a JACC provider within Liberty, but unfortunately the documentation is not entirely clear, and even less fortunately it's not fully correct.

As in some of the other documents from IBM the JACC installation has some very terse instructions. They may be clear if you're a rather experienced Liberty and/or OSGi user, but if you're not a sentence like the following might be a bit puzzling:

Package the component into an OSGi bundle that is part of your user feature, along with your JACC provider.
The above is more a summary of what we have to do, not how to actually do it. We look at the how in some more detail below:

Create an OSGi bundle

Luckily IBM also has instructions for a "hello world" user feature, which are much more complete and easier to follow. Not so lucky was that after creating an "OSGI Bundle Project" as indicated by those instructions I got a compile error right away in the project. For some unfathomable reason the package org.osgi.framework could not be found. Eventually it appeared that next to a target runtime (which was set to the installed Liberty server), Eclipse also has the notion of a target platform. The first one normally provides the packages a project compiles against, but in an OSGi project things are never that simple. The target platform changes automatically when you set the target runtime for your project, even though for former is global for your entire workspace and the latter is per project.

The target platform can be set in Eclipse in Preferences -> Plug-in Development -> Target Platform. See the screenshot below:

Switching to "Running platform" solved the compile error for org.osgi.framework, but the IBM specific bundles couldn't be resolved then. Switching to "Liberty beta 2016.8 with SPI" solved the problem, but later on I could switch back to "Liberty beta 2016.8" without the compile error coming back. Eclipse sometimes works in mysterious ways.

Add our JACC provider jar to this bundle

Not mentioned anywhere in the IBM documentation, but the existing JACC provider jar had to be copied into the BundleContent folder of the OSGi bundle project. The Eclipse manifest editor (runtime tab -> classpath pane) for some reason doesn't let you pick from this location, but it can be easily added directly to the MANIFEST.FM file by adding the following to it:


Bundle-ClassPath: .,
cdi-jacc-provider-0.1-SNAPSHOT.jar
After the JACC provider jar has been added in this way, the manifest editor shows the jar, but it will not have been added to the classpath of the project itself. This has to be done separately by going to project -> properties -> Java Build Path -> Libraries and adding the jar there too. See the screenshot below:

Implement a Liberty specific service that returns the policy and factory instances from our provider

Contrary to all other servers, Liberty requires an amount of Liberty specific code in the module. The above mentioned instructions give an example of this, but unfortunately that code for a required service seemed to be rather faulty. Among others several imports were missing, the "getPolicyConfigurationFactory" method name was wrong (should be "getPolicyConfigFactory"), the return type of that same method was wrong (instead of "Policy" it should be "PolicyConfigurationFactory", then there's an active method that used a variable called "configprops" that's not defined anywhere, etc.

Additionally, the service uses the @Component annotation, which is said to generally make things easier, but I wasn't able to use it. After importing the right package for it, Liberty kept logging the following error when starting up:

[ERROR ] CWWKE0702E: Could not resolve module: JaccBundle [250] Unresolved requirement: Import-Package: org.osgi.service.component.annotations; version="1.3.0"

Being unable to resolve this, I removed the annotation and implemented a traditional Activator instead. The code for both the service and the activator is shown below:

Service:


package jaccbundle;

import static java.lang.System.setProperty;
import static java.lang.Thread.currentThread;

import java.security.Policy;

import javax.security.jacc.PolicyConfigurationFactory;

import org.omnifaces.jaccprovider.jacc.policy.DefaultPolicy;

import com.ibm.wsspi.security.authorization.jacc.ProviderService;

public class MyJaccProviderService implements ProviderService {

@Override
public Policy getPolicy() {
return new DefaultPolicy();
}

@Override
public PolicyConfigurationFactory getPolicyConfigFactory() {

ClassLoader originalContextClassloader =
currentThread().getContextClassLoader();
try {
currentThread()
.setContextClassLoader(
this.getClass().getClassLoader());

setProperty(
"javax.security.jacc.PolicyConfigurationFactory.provider",
"org.omnifaces.jaccprovider.jacc.configuration.TestPolicyConfigurationFactory");

return PolicyConfigurationFactory.getPolicyConfigurationFactory();
} catch (Exception e) {
return null;
} finally {
Thread.currentThread()
.setContextClassLoader(
originalContextClassloader);
}
}
}

Activator


package jaccbundle;

import static org.osgi.framework.Constants.SERVICE_PID;

import java.util.Hashtable;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

import com.ibm.wsspi.security.authorization.jacc.ProviderService;

public class Activator implements BundleActivator {

private static final String CONFIG_PID = "jaccBundle";
private ServiceRegistration<ProviderService> jaccProviderService;

public void start(BundleContext context) throws Exception {
jaccProviderService = context.registerService(
ProviderService.class,
new MyJaccProviderService(),
getDefaults());
}

public void stop(BundleContext context) throws Exception {
if (jaccProviderService != null) {
jaccProviderService.unregister();
jaccProviderService = null;
}
}

Hashtable<String, ?> getDefaults() {
Hashtable<String, String> defaults = new Hashtable<>();
defaults.put(SERVICE_PID, CONFIG_PID);
return defaults;
}

}

Make sure we have the right imports and exports

The Eclipse manifest editor offers a handy "Analyze code and add dependencies to the MANIFEST.FM" feature, but like the matter duplicator it doesn't work and has never worked. They can be added manually though. In the editor it's Dependencies -> Imported packages for the imports, and Runtime -> Exported packages for the exports. See below:

After some trial and error the MANIFEST.FM eventually looked like this:


Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: JaccBundle
Bundle-SymbolicName: JaccBundle
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: jaccbundle.Activator
Bundle-ClassPath: .,
cdi-jacc-provider-0.1-SNAPSHOT.jar
Import-Package: com.ibm.wsspi.security.authorization.jacc;version="1.0.0",
javax.enterprise.context;version="1.1.0",
javax.enterprise.context.spi;version="1.1.0",
javax.enterprise.inject;version="1.1.0",
javax.enterprise.inject.spi;version="1.1.0",
javax.inject;version="1.0.0",
javax.naming,
javax.security.auth,
javax.security.jacc;version="1.5.0",
org.osgi.framework
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: jaccbundle,
org.omnifaces.jaccprovider.cdi,
org.omnifaces.jaccprovider.jacc

Create a Liberty Feature that references the previously created bundle and provides the right exports

After having created the Liberty Feature project using the IBM instruction for the hello world feature, there's relatively little to be done here. We do have to add the exports that we already exported from the bundle again here.

This can be done via the editor for the one and only file in our feature project called SUBSYSTEM.FM:

The raw file will then look as follows:

Subsystem-ManifestVersion: 1.0
IBM-Feature-Version: 2
IBM-ShortName: JaccFeature
Subsystem-SymbolicName: JaccFeature;visibility:=public
Subsystem-Version: 1.0.0.qualifier
Subsystem-Type: osgi.subsystem.feature
Subsystem-Content: JaccBundle;version="1.0.0"
Manifest-Version: 1.0
IBM-API-Package: org.omnifaces.jaccprovider.cdi,
org.omnifaces.jaccprovider.jacc
The IBM JACC installation instructions mentioned one other point here:
Ensure that your feature includes the OSGi subsystem content: com.ibm.ws.javaee.jacc.1.5; location:="dev/api/spec/".
I could however not get this to work. Adding it to SUBSYSTEM.FM as follows:

Subsystem-Content: JaccBundle;version="1.0.0",com.ibm.ws.javaee.jacc.1.5;location:="dev/api/spec/"
Resulted in the following error when starting Liberty:

Bundle location:="dev/api/spec/" cannot be
resolved
Adding it as:

Subsystem-Content: JaccBundle;version="1.0.0",com.ibm.ws.javaee.jacc.1.5
Yielded the following error:

[ERROR ] CWWKE0702E: Could not resolve module: com.ibm.ws.javaee.jacc.1.5 [251]
Another singleton bundle selected: osgi.identity; osgi.identity="com.ibm.ws.javaee.jacc.1.5"; type="osgi.bundle"; version:Version="1.0.13.20160722-1732"; singleton:="true"
Without this directive the JACC provider already worked as expected, so I just left it out. It's intended use is somewhat puzzling though.

The workspace with all artefacts combined for the two required projects looks as follows:

Installing the feature in Liberty

As explained in the hello world instructions by IBM, the feature with the embedded bundle with the embedded JACC provider jar can be installed via the Feature project by right clicking on it in Eclipse and selecting "Install Feature". After that is done, the final step is to add the new feature to Liberty's server.xml file, for which there again is a graphical editor in Eclipse:

The raw file look as follows:


<server description="Liberty beta">

<featureManager>
<feature>javaee-7.0</feature>
<feature>localConnector-1.0</feature>
<feature>usr:JaccFeature</feature>
</featureManager>

<httpEndpoint httpPort="8080" httpsPort="9443" id="defaultHttpEndpoint"/>

<webContainer deferServletLoad="false"/>
<ejbContainer startEJBsAtAppStart="true"/>

<applicationManager autoExpand="true"/>
<applicationMonitor updateTrigger="mbean"/>

</server>

After this we can finally run a web application to test things, and it indeed seems to work as expected!

One thing to keep in mind is that Liberty initialises the CDI request scope rather late (after authentication has been done). For some of the calls to our custom JACC provider this is way too late. Fortunately, CDI *does* work, but only for scopes that don't depend on the current request (like the application scope).

The authorization mechanism as demonstrated in the previous article most naturally uses the application scope anyway, so here that's no problem. For the brave, the request scope for CDI can forcefully and in a hacky way be activated earlier (e.g. in a JASPIC SAM) as follows:


Object weldInitialListener = request.getServletContext().getAttribute("org.jboss.weld.servlet.WeldInitialListener");
ServletRequestEvent event = new ServletRequestEvent(request.getServletContext(), request);

ELProcessor elProcessor = new ELProcessor();
elProcessor.defineBean("weldInitialListener", weldInitialListener);
elProcessor.defineBean("event", event);
elProcessor.eval("weldInitialListener.requestInitialized(event)");
Note again that this is a hack, and as such not guaranteed to work without any problems or keep working on newer versions of Liberty. It was only briefly tested on Liberty Beta 2016.8

Conclusion

Installing a JACC provider on Liberty is a lot of work. The vendor documentation is not clear on this and even contains errors. After a user feature has been created it's relatively easy though to add it to Liberty. Publishing it to a repository (not discussed in the article) would make it even easier to use the JACC provider on other instances of Liberty.

The amount of work that's required and the need to dive into vendor specific documentation could largely be eliminated by having a Java EE standard way to add a JACC provider from within an application (like what is currently possible for JASPIC SAMs). Hopefully a JACC MR will consider this.

Regardless, with the JACC provider installed once Liberty users can from then on easily add custom authorization rules to their applications. Care should be taken though that the JACC provider is just a POC. It shows great promise, but has not been extensively tested yet.

Arjan Tijms

The state of portable authentication in Java EE, end 2016 update

$
0
0
In the beginningand middle of this year we looked at how well modern Java EE servers supported portable authentication (JASPIC) in Java EE. As the end of 2016 approaches we take a third look to see how things are progressing.

Since our last time new versions of all servers have been released. Payara went from 163-beta to 164, WildFly went from 10.0 to 10.1, Liberty beta went from 2016-5 to 2016-11, WebLogic went from 12.2.1 to 12.2.1.2 and TomEE went from 7.0 to 7.0.2. We also added a new server, namely Tomcat. Tomcat was indirectly already tested via TomEE, but given the importance of standalone Tomcat we decided to put this one in explicitly. Do note that Tomcat is not a full or web profile Java EE server, so the integration tests for technologies it doesn't support (like JSF, CDI, etc) are simply omitted.

Tests were added for request.authenticate, an injected CDI request, the servlet path after a forward, isMandatory in a SAM, and finally for a SAM request to be seen by a Filter. For the first time there was also a test removed, namely including a JSF based resource from a SAM. This fails on many servers but the failure appeared to be a general JSF failure unrelated to JASPIC and/or its integration with the Java EE environment.

The results of running the latest series of JASPIC tests are shown below:

Running the Java EE 7 samples JASPIC tests
ModuleTestPayara 164WildFly 10.1Liberty 2016-11Weblogic 12.2.1.2TomEE 7.0.2Tomcat 8.5.6
async-authenticationtestBasicAsync
Passed
Passed
Passed
Passed
Passed
-
basic-authenticationtestProtectedPageNotLoggedin
Passed
Passed
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedPageLoggedin
Passed
Passed
Passed
Passed
Passed
Passed
basic-authenticationtestPublicPageLoggedin
Passed
Passed
Passed
Passed
Passed
Passed
basic-authenticationtestPublicPageNotLoggedin
Passed
Passed
Passed
Passed
Passed
Passed
basic-authenticationtestPublicAccessIsStateless
Passed
Passed
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedAccessIsStateless
Passed
Passed
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedAccessIsStateless2
Passed
Passed
Passed
Passed
Passed
Passed
basic-authenticationtestProtectedThenPublicAccessIsStateless
Passed
Passed
Passed
Passed
Passed
Passed
custom-principaltestProtectedPageLoggedin
Passed
Passed
Passed
Failure
Passed
Passed
custom-principaltestPublicPageLoggedin
Passed
Passed
Passed
Failure
Passed
Passed
custom-principaltestPublicAccessIsStateless
Passed
Passed
Passed
Passed
Passed
Passed
custom-principaltestProtectedAccessIsStateless
Passed
Passed
Passed
Passed
Passed
Passed
custom-principaltestProtectedAccessIsStateless2
Passed
Passed
Passed
Passed
Passed
Passed
custom-principaltestProtectedThenPublicAccessIsStateless
Passed
Passed
Passed
Passed
Passed
Passed
dispatchingtestBasicForwardViaProtectedResource
Passed
Passed
Passed
Passed
Passed
Passed
dispatchingtestBasicForwardViaPublicResource
Passed
Passed
Passed
Passed
Passed
Passed
dispatchingtestBasicIncludeViaPublicResource
Passed
Passed
Passed
Passed
Passed
Passed
dispatching-jsf-cditestCDIForwardWithRequestProtected
Passed
Passed
Passed
Passed
Passed
-
dispatching-jsf-cditestCDIForwardWithRequestInjectPublic
Passed
Passed
Passed
Passed
Failure
-
dispatching-jsf-cditestCDIForwardViaProtectedResource
Passed
Passed
Passed
Passed
Passed
-
dispatching-jsf-cditestCDIForwardViaPublicResource
Passed
Passed
Passed
Passed
Passed
-
dispatching-jsf-cditestCDIForwardWithRequestPublic
Passed
Passed
Passed
Passed
Passed
-
dispatching-jsf-cditestCDIForwardWithRequestInjectProtected
Passed
Passed
Passed
Passed
Failure
-
dispatching-jsf-cditestCDIIncludeViaPublicResource
Passed
Passed
Passed
Passed
Passed
-
dispatching-jsf-cditestJSFwithCDIForwardViaPublicResource
Passed
Passed
Passed
Passed
Passed
-
dispatching-jsf-cditestJSFwithCDIForwardViaProtectedResource
Passed
Passed
Passed
Passed
Passed
-
dispatching-jsf-cditestJSFForwardViaPublicResource
Passed
Passed
Passed
Passed
Passed
-
dispatching-jsf-cditestJSFForwardViaProtectedResource
Passed
Passed
Passed
Passed
Passed
-
ejb-propagationpublicServletCallingProtectedEJB
Passed
Passed
Passed
Failure
Passed
-
ejb-propagationprotectedServletCallingProtectedEJB
Passed
Passed
Passed
Failure
Passed
-
ejb-propagationpublicServletCallingPublicEJBThenLogout
Passed
Passed
Passed
Passed
Passed
-
ejb-propagationprotectedServletCallingPublicEJB
Passed
Passed
Passed
Passed
Passed
-
ejb-register-sessiontestRemembersSession
Passed
Passed
Passed
Failure
Passed
-
ejb-register-sessiontestRemembersSession
Passed
Passed
Passed
Failure
Passed
-
invoke-ejb-cdiprotectedInvokeCDIFromSecureResponse
Passed
Passed
Failure
Failure
Passed
-
invoke-ejb-cdiprotectedInvokeCDIFromCleanSubject
Passed
Passed
Passed
Passed
Passed
-
invoke-ejb-cdiprotectedInvokeCDIFromValidateRequest
Passed
Passed
Failure
Failure
Passed
-
invoke-ejb-cdipublicInvokeCDIUseInjectedRequestFromValidateRequest
Passed
Passed
Failure
Failure
Passed
-
invoke-ejb-cdipublicInvokeCDIFromSecureResponse
Passed
Passed
Failure
Failure
Passed
-
invoke-ejb-cdipublicInvokeCDIFromValidateRequest
Passed
Passed
Failure
Failure
Passed
-
invoke-ejb-cdipublicInvokeCDIUseInjectedRequestFromCleanSubject
Passed
Passed
Passed
Passed
Passed
-
invoke-ejb-cdipublicInvokeCDIUseInjectedRequestFromSecureResponse
Passed
Passed
Failure
Failure
Passed
-
invoke-ejb-cdipublicInvokeCDIFromCleanSubject
Passed
Passed
Passed
Passed
Passed
-
invoke-ejb-cdiprotectedInvokeEJBFromSecureResponse
Passed
Passed
Passed
Passed
Passed
-
invoke-ejb-cdiprotectedInvokeEJBFromCleanSubject
Passed
Passed
Passed
Passed
Passed
-
invoke-ejb-cdiprotectedInvokeEJBFromValidateRequest
Passed
Passed
Passed
Passed
Passed
-
invoke-ejb-cdipublicInvokeEJBFromSecureResponse
Passed
Passed
Passed
Passed
Passed
-
invoke-ejb-cdipublicInvokeEJBFromValidateRequest
Passed
Passed
Passed
Passed
Passed
-
invoke-ejb-cdipublicInvokeEJBFromCleanSubject
Passed
Passed
Passed
Passed
Passed
-
jacc-propagationcallingJACCWhenAuthenticated
Passed
Passed
Failure
Failure
Failure
-
jacc-propagationcallingJACCWhenAuthenticated
Passed
Passed
Failure
Failure
Failure
-
jacc-propagationcallingJACCWhenNotAuthenticated
Passed
Passed
Failure
Failure
Failure
-
lifecycletestBasicSAMMethodsCalled
Passed
Passed
Passed
Passed
Passed
Passed
lifecycletestLogout
Passed
Passed
Passed
Passed
Passed
Passed
lifecycletestProtectedIsMandatory
Passed
Passed
Passed
Passed
Passed
Passed
lifecycletestPublicIsNonMandatory
Passed
Passed
Passed
Passed
Passed
Passed
programmatic-authenticationtestAuthenticateFailFirstTwice
Passed
Passed
Passed
Passed
Passed
Passed
programmatic-authenticationtestAuthenticate
Passed
Passed
Passed
Passed
Passed
Passed
programmatic-authenticationtestAuthenticateFailFirstOnce
Passed
Passed
Passed
Passed
Passed
Passed
register-sessiontestJoinSessionIsOptional
Passed
Passed
Passed
Failure
Passed
Passed
register-sessiontestRemembersSession
Passed
Passed
Passed
Failure
Passed
Passed
register-sessiontestJoinSessionIsOptional
Passed
Passed
Passed
Failure
Passed
Passed
register-sessiontestRemembersSession
Passed
Passed
Passed
Failure
Passed
Passed
status-codestest404inResponse
Passed
Passed
Passed
Passed
Passed
Passed
status-codestest404inResponse
Passed
Passed
Passed
Passed
Passed
Passed
wrappingtestResponseWrapping
Passed
Passed
Passed
Passed
Passed
Passed
wrappingtestDeclaredFilterResponseWrapping
Passed
Passed
Failure
Passed
Passed
Passed
wrappingtestProgrammaticFilterResponseWrapping
Passed
Passed
Failure
Passed
Passed
Passed
wrappingtestDeclaredFilterRequestWrapping
Passed
Passed
Failure
Passed
Passed
Passed
wrappingtestProgrammaticFilterRequestWrapping
Passed
Passed
Failure
Passed
Passed
Passed
wrappingtestRequestWrapping
Passed
Passed
Passed
Passed
Passed
Passed

As can be see we now have 3 perfectly scoring servers; Payara, WildFly and Tomcat now pass every test being thrown at them. All 3 do this for the first time, and the slightly older versions of each of them contain a variety of (small) bugs that prevents a perfect score.

Liberty still fails the CDI tests as before, but there's a hack available that can let Liberty pass these. Since we test as much as possible out of the box here this hack was not applied. JACC propagation also doesn't work, but this is because there's no JACC provider available by default.

Perhaps the most surprising result of this round is that WebLogic is not longer completely broken when it comes to JASPIC. While WebLogic 12.1.x had decent support for JASPIC, a major regression was introduced in 12.2.1.0 were the basic cases didn't work properly anymore. When the basic cases fail it's almost pointless to continue testing since in practice when an authentication itself doesn't work anymore it doesn't matter so much whether say request wrapping is supported or not. WebLogic does have major problems with the "register session" feature (which likely caused the regression with basic authentication in the first place), doesn't support setting a custom principal (a major feature of JASPIC), and has problems with propagating to EJB. WebLogic fails the same CDI and JACC tests as Liberty does. Contrary to Liberty, WebLogic -does- have a default JACC provider but it's not activated out of the box.

TomEE performs very well, but has a small hick up when an injected request is used in a forwarded resource. It also fails the JACC propagation, but this is because TomEE doesn't implement JACC at all for the Web module (only for EJB).

An important additional aspect not shown in the test table above is whether JASPIC works out of the box (like e.g. a Servlet Filter does), or whether it needs (server specific) activation of some sort.

In this regard, Liberty, WebLogic, TomEE and Tomcat need zero activation. There's a small caveat with Liberty and that's if you use the server specific group to role mapping in combination with a JASPIC SAM, all role checking fails. This is a somewhat peculiar incompatibility. All other servers don't care whether the groups that are set come from a portable JASPIC SAM or from something proprietary when doing the server specific/proprietary group to role mapping.

Payara and WildFly both need an activation of some kind. Payara needs a glassfish-web.xml where default group to role mapping is activated (or alternatively, where groups are actually mapped to roles), while WildFly needs a jboss-web.xml where the "jaspitest" security domain is set. WildFly should eventually lift this mandated activation when the new Elytron security system is introduced, which could possibly happen in WildFly 11. Payara could eventually default to default group to role mapping. WebLogic made this move before, but this is somewhat of a major change that should be done carefully if indeed planned.

Conclusion

Three servers, namely WildFly 10.1, Payara 164 and Tomcat 8.5.6 now pass all tests, but two of them (WildFly and Payara) need some kind of activation so are not perfect-perfect, but still very, very close to it. TomEE performs very well too, with only a minor regression and all the major core authentication functionality working perfectly.

Liberty and WebLogic have a bit more work left to be done, where as core features are concerned Liberty fails the request/response wrapping partially, while WebLogic fails the custom principal, register session and EJB propagation.

In a next article we'll be looking at what things look like after we applied the CDI/Weld hack for Liberty and Weblogic, and if JACC propagation works on them when we install/activate a JACC provider.

Arjan Tijms

JSF 2.3 released!

$
0
0
After a long and at times intense spec and development process the JSF 2.3 EG is proud to announce that today we've released JSF 2.3.

JSF (JavaServer Faces), is a component based MVC framework that's part of Java EE. JSF 2.3 in particular is part of Java EE 8.

Major new features in JSF 2.3 are a tighter integration with CDI, support for WebSockets, a really cool component search expression framework (donated by PrimeFaces), basic support for extensionless URLs, and class level bean validation.

The age old native managed beans of JSF 2.3 have finally been deprecated (although they are still available for now) in favour of CDI. It's expected that these will be fully removed (pruned) in a future release.

The JSF 2.3 EG would like to thank everyone who contributed to JSF in whatever way, by creating bug reports, testing builds, providing comments and insights on the mailinglist and contributing code. Without those community contributions JSF 2.3 would not have been possible! Thanks to all our fantastic community members!

JSF 2.3 (Mojarra 2.3) can be downloaded per direct from the project's download page.

Maven coordinates for the implementation (includes API) are:


<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.3.0</version>
</dependency>

The full implementation can be used for Servlet containers such as Tomcat and Jetty.

Maven coordinates for just the API are:


<dependency>
<groupId>javax.faces</groupId>
<artifactId>javax.faces-api</artifactId>
<version>2.3</version>
</dependency>

The API jar can only be used as a compile time dependency.

Application servers Payara and GlassFish can be trivially updated by replacing the JSF 2.2 glassfish/modules/javax.faces.jar with the 2.3 version. It's usually a good idea to clear the OSGI cache after that (e.g. rm -rf [payara/gf gome]/ glassfish/domains/domain1/osgi-cache/felix/)

Arjan Tijms


Draft list of changes in Servlet 4.0

$
0
0
The proposed final draft (PDF) of the Servlet 4.0 spec has just been made available at GitHub.

The major new feature is HTTP/2 support and specifically the push support that comes with it. Java EE already has support for push via WebSockets (including WebSocket support in JSF 2.3), but there are other interesting changes as well, such as for instance the Mapping Discovery API.

The following contains a terse list of changes, taken from section A.1 of the above linked Servlet 4.0 PFD document. All mentioned references to sections are to that document.

  1. Requirement to support HTTP/2, see Section 1.2, “What is a Servlet Container?” on page 1-1 and “What is a Servlet?” on page 1 1. This includes HTTP/2 server push, see “HTTP/2 Server Push” on page 3 29.
  2. Modify javadoc for ServletContext getAttribute() and getInitParameter(), specify that NullPointerException must be thrown if the argument “name” is null.
  3. Modify javadoc for ServletContext.setAttribute() and setInitParameter() to specify that NullPointerException must be thrown if the “name” argument is null.
  4. DeprecateHttpServletRequestWrapper.isRequestedSessionIdFromUrl().
  5. Add @Deprecated to classes and methods with @deprecated in javadoc: ServletContext, ServletRequestWrapper, SingleThreadModel, UnavailableException, HttpServletRequest, HttpServletResponse, HttpServletResponseWrapper, HttpSession, HttpSessionContext, HttpUtils.
  6. Add default-context-path in the schema of web.xml and the description in Section 30., “default-context-path Element” on page 14-180 and the figure, Section FIGURE 14-1, “web-app Element Structure”.
  7. Modify Section 7.7.1, “Threading Issues” to clarify non-thread safety of objects vended from requests and responses.
  8. Clarify metadata-complete in Section 8.1, “Annotations and pluggability”.
  9. Add default to methods in ServletContextAttributeListener, ServletContextListener, ServletRequestAttributeListener, ServletRequestListener, HttpSessionActivationListener, HttpSessionAttributeListener, HttpSessionBindingListener, HttpSessionListener.
  10. Add javax.servlet.GenericFilter and javax.servlet.http.HttpFilter
  11. Clarify the merging of in web.xml and web-fragment.xml in Section 8.2.3, “Assembling the descriptor from web.xml, web-fragment.xml and annotations”.
  12. Modify javadoc for ServletContext.getEffectiveSessionTrackingModes() without specifying the default value.
  13. Remove DTDs and Schemas from binary artifact for Servlet API.
  14. Add getSessionTimeout and setSessionTimeout in ServletContext. See javadoc, Section 4.4.4 and Section 7.5.
  15. Add addJspFile() in ServletContext. See javadoc, Section 4.4.1.4 and Section 4.4.1.7.
  16. Add request-character-encoding and response-character-encoding in the schema of web.xml. See the corresponding descriptions of the elements in Section 31. and Section 32.
  17. Add getRequestCharacterEncoding, setRequestCharacterEncoding, getResponseCharacterEncoding and setResponseCharacterEncoding in ServletContext. Update the corresponding javadoc of ServletContext, ServletRequest and ServletResponse. See Section 4.4.5, Section 3.12 and Section 5.6.
  18. Describe mapping discovery API. See Section 12.3, “Runtime Discovery of Mappings”.
  19. Update the javadoc of Registration, ServletContext, ServletRegistration for the behaviors of returned sets.
  20. Clarify the behaviors of complete and dispatch in AsyncContext before the container-initiated dispatch that called startAsync has returned to the container. See Section , “AsyncContext” on page 2-13.
  21. Clarify interpretation of fileName parameter for method Part.write(). See the javadoc for details.
  22. Clarify encoding used for reading the request URL. See Section 12.1, “Use of URL Paths” on page 12-125 for details.
  23. Specified support for HTTP trailer. See Section 5.3, “HTTP Trailer” for details. Add getTrailerFields(), isTrailerFieldsReady() in HttpServletRequest and setTrailerFields in HttpServletResponse. See the corresponding javadoc.

Should the community take over JSF.next or not?

$
0
0
JSF aka JavaServer Faces is a component based MVC framework that's part of Java EE and is one of the oldest Java MVC frameworks that's still supported and actively used (version 1.0 was released in 2004).

Over time, Java EE itself has grown considerably and as such the resources required to maintain and evolve Java EE have grown as well. Now Oracle has indicated at several occasions that it just doesn't have the resources required for this, and for most constituent specs of Java EE it can do at most small updates, but in other cases can't do any updates at all.

In order to lessen this immense burden on Oracle somewhat, the community has largely taken over for JSF 2.3 and Java EE Security API 1.0. The following graph (taken from a presentation by JSF spec lead Ed Burns) gives an indication:

The question is how to continue for JSF.next?

Since the community has largely taken over JSF already, should this perhaps be made more formal by actually letting the community (individual, foundation, or even representative small company) take the lead in developing the next version of JSF? In such scenario, the existing JSF versions (2.3 and before) and their respective TCKs would stay with Oracle, but JSF.next (i.e. JSF 2.4 or 3.0) would be fully specified, implemented and released by the community (OmniFaces in particular, with possibly the help of others).

Is a large and important spec such as JSF better off at a large and responsible, albeit resource constrained, organisation such as Oracle, or do you want OmniFaces to take over the spec lead role? If you want, you can cast a vote in the poll below or leave a comment:

Do you want OmniFaces to take over the JSF spec lead role?

Dynamic beans in CDI 2.0

$
0
0
A while ago we wrote about CDIs ability to dynamically add Bean<T> instances to the CDI runtime.

A Bean<T> is a kind of factory for beans, that makes types available for injection, lookup via the bean manager, or by referencing them in expression language. CDI producers (via the @Produces annotation) fulfil a somewhat similar role, but they essentially only make the "create instance" method dynamic; the rest (like scope, types, etc) is more or less static. A programmatically added Bean<T> essentially makes all those aspects dynamic.

As the previous article showed, dynamically adding such Bean<T> is a bit more work and it's quite verbose, as well as a little complex as the developer has to find out what to return as a default for various methods that are not directly of interest.

CDI 2.0 has addressed some of the above issues by providing a very convenient builder that not only makes creating a Bean<T> instance far less verbose, but also takes away most of the guesswork. The following shows an example:


public class CdiExtension implements Extension {

public void afterBean(final @Observes AfterBeanDiscovery afterBeanDiscovery) {
afterBeanDiscovery
.addBean()
.scope(ApplicationScoped.class)
.types(MyBean.class)
.id("Created by " + CdiExtension.class)
.createWith(e -> new MyBeanImpl("Hi!"));
}
}

The above makes a bean available for injection into MyBean injection points and with the @ApplicationScoped scope, backed by a MyBeanImpl class.

A fully working example is provided in the Java EE 8 Samples project.

The example was tested on Payara Server 5, of which a snapshot can be downloaded from the snapshot repository. An initial alpha will be released very soon, but in the mean time the latest version can be downloaded here:
payara-5.0.0.173-SNAPSHOT.zip.

Arjan Tijms

Extensionless URLs with JSF 2.3

$
0
0
An extensionless URL is a URL without a final suffix like .xhtml, .html, .jsp, etc. Such a suffix is seen as technical "clutter" that's hard to remember for humans. Servers often need it though to route a request to the right controller.

JSF, a Java EE MVC framework, has supported extensionless URLs for some time via PrettyFaces (now merged to the general Rewrite framework) and OmniFaces. Both of these solutions used various workarounds to trick JSF into working with extensionless URLs.

Though JSF 2.3 does, unfortunately, still not support extensionless URLs fully out of the box via e.g. a single parameter, it can provide support for it by basically combining the new support for exact mapping and the API for obtaining a list of all view resources. Additionally combining this with the Servlet 3.1 feature for dynamically adding Servlet mappings and some JDK8 streaming and lambdas, makes it possible to enable extensionless support with just 2 statements (albeit somewhat long statements):


@WebListener
public class MappingInit implements ServletContextListener {

@Override
public void contextInitialized(ServletContextEvent sce) {
FacesContext context = FacesContext.getCurrentInstance();

sce.getServletContext()
.getServletRegistrations()
.values()
.stream()
.filter(e -> e.getClassName().equals(FacesServlet.class.getName()))
.findAny()
.ifPresent(
reg -> context.getApplication()
.getViewHandler()
.getViews(context, "/", RETURN_AS_MINIMAL_IMPLICIT_OUTCOME)
.forEach(e -> reg.addMapping(e)));
}
}

What the above code does is finding the existing FacesServlet, then getting all views for the entire application in a form that happens to be exactly suitable for extensionless URLs, and then adding each of them as mapping to the FacesServlet we previously found.

After adding the above shown WebListener to an application, its view can be requested via URLs like example.com/login, example.com/users/all etc.

The example was tested on Payara Server 5, of which a snapshot can be downloaded from the snapshot repository. An initial alpha will be released very soon, but in the mean time the latest version can be downloaded here:
payara-5.0.0.173-SNAPSHOT.zip.

Arjan Tijms

Dynamically adding an interceptor to a build-in CDI bean

$
0
0
In Java EE's CDI, beans can be augmented via 2 artefacts; Decorators and Interceptors.

Decorators are typically owned by the application code and can decorate a bean that's shipped by the container (build-in beans) or a library.

Interceptors are typically shipped by a library and can be applied (bound) to a bean that's owned by the application.

So how do you bind a library shipped interceptor to a library shipped/build-in bean? In CDI 1.2 and before this wasn't really possible, but in CDI 2.0 we can take advantage of the new InterceptionFactory to do just this. It's not entirely trivial yet, but it's doable. In this article we'll demonstrate how to apply the @RememberMe interceptor binding from the new Java EE 8 Security spec to a build-in bean of type HttpAuthenticationMechanism, which is from the Security spec as well.

First we configure our authentication mechanism by means of the following annotation:


@BasicAuthenticationMechanismDefinition(
realmName="foo"
)

 

This will cause the container to enable a build-in bean with interface type HttpAuthenticationMechanism, but having an unknown (vendor specific) implementation.

Next we'll definite an alternative for this bean via a CDI producer:


@Alternative
@Priority(500)
@ApplicationScoped
public class ApplicationInit {

@Produces
public HttpAuthenticationMechanism produce(InterceptionFactory<HttpAuthenticationMechanismWrapper> interceptionFactory, BeanManager beanManager) {
return ...
}
Note that perhaps somewhat counter intuitively the @Alternative annotation is put on the bean hosting the producer method, not on the producer method itself.

A small challenge here is to obtain the bean with type HttpAuthenticationMechanism that would have been chosen by the CDI runtime had our producer not been there. For a decorator this is easy as CDI makes that exact bean injectable via the @Decorated qualifier. Here we'll have to do this manually. One way is to get all the beans of type HttpAuthenticationMechanism from the bean manager (this will include both alternatives and non-alternatives), filter ourselves from that set and then let the bean manager resolve the set to the one that would be chosen for injection. We then create a reference for that chosen bean.

The following shows this in code:


HttpAuthenticationMechanism mechanism =
createRef(
beanManager.resolve(
beanManager.getBeans(HttpAuthenticationMechanism.class)
.stream()
.filter(e -> !e.getBeanClass().equals(ApplicationInit.class))
.collect(toSet())),
beanManager);

 

With createRef being defined as:


HttpAuthenticationMechanism createRef(Bean<?> bean, BeanManager beanManager) {
return (HttpAuthenticationMechanism)
beanManager.getReference(
bean,
HttpAuthenticationMechanism.class,
beanManager.createCreationalContext(bean));
}

 

We now have an instance to the bean to which we like to apply the interceptor binding. Unfortunately, there's a somewhat peculiar and very nasty note in the CDI spec regarding the method that creates a proxy with the required interceptor attached:

If the provided instance is an internal container construct (such as client proxy), non-portable behavior results.

Since the HttpAuthenticationMechanism is a client proxy (it's application scoped by spec definition) we have no choice but to introduce some extra ceremony here and that's by providing a wrapper ourselves. The interceptor will be applied to the wrapper then, and the wrapper will delegate to the actual HttpAuthenticationMechanism instance:

 


HttpAuthenticationMechanismWrapper wrapper =
new HttpAuthenticationMechanismWrapper(mechanism);

 

Having our HttpAuthenticationMechanism instance ready, we can now dynamically configure an annotation instance. Such instance can be created via CDI's provided AnnotationLiteral helper type:


interceptionFactory.configure().add(
new RememberMeAnnotationLiteral(
86400, "", // cookieMaxAgeSeconds
false, "", // cookieSecureOnly
true, "", // cookieHttpOnly
"JREMEMBERMEID", // cookieName
true, "" // isRememberMe
)
);

 

Finally, we create the above mentioned new proxy with the configured interceptor binding applied to it using the interception factory's createInterceptedInstance method and return this from our producer method:


return interceptionFactory.createInterceptedInstance(
new HttpAuthenticationMechanismWrapper(wrapper));

 

A full example can be found in the Java EE 8 samples project.

Note that there's a small caveat here; if the Interceptor needs access to the interceptor bindings (which is almost always the case when the binding has attributes), you can't just inspect the target type as one would usually do in CDI 1.2 and earlier code. The interceptor binding annotation is not physically present on the type. At the moment it's not entirely clear how to obtain these in a portable way. The interceptors in the Java EE Security RI (Soteria) uses an RI specific way for now.

The example was tested on Payara Server 5, of which a snapshot can be downloaded from the snapshot repository. An initial alpha will be released very soon, but in the mean time the latest version can be downloaded here:
payara-5.0.0.173-SNAPSHOT.zip.

Arjan Tijms

Payara 5 RC1 available for testing

$
0
0
We are happy to announce that Payara 5 release candidate 1 is now available for download.

Payara 5 is the first release that will include all of the Java EE 8 and MicroProfile 1.2 components, including a special build of Mojarra (JSF 2.3) based on the 2.4 master in which a lot of refactoring has been done, and a special build of Soteria (Java EE Security) based on the 1.1 master with several bug fixes.

The full list of changes are available from the links given below:

Payara 5 runs all the Java EE 7 samples, all the Java EE 8 samples and all of the MicroProfile 1.2 samples.

If no major bugs surface Payara 5 Final should be released soon.

Arjan Tijms

Java EE Survey 2018

$
0
0
At OmniFaces we poll the community from time to time about Java EE and related technologies. With all the changes that are about to happen with the move of Java EE to Eclipse and the subsequent renaming to Jakarta EE, we expanded the survey a little for this year.

In the 2018 edition, there are 4 categories of questions:

  • Current usage of Java EE
  • Servlet containers
  • APIs related to Java EE
  • The future of Java EE / Jakarta EE

Jakarta EE provides the opportunity to revitalise and modernise Java EE, but in order to do that it's more important than ever that we know what matters to all of its users out there.

So therefor we'd like to invite all Java EE users to participate in The Java EE Survey 2018


Java EE Survey 2018 - results

$
0
0
At OmniFaces we poll the community from time to time about Java EE and related technologies. With all the changes that are about to happen with the move of Java EE to Eclipse and the subsequent renaming to Jakarta EE, we expanded the survey a little for this year.

In the 2018 edition, there were 4 categories of questions:

  • Current usage of Java EE
  • Servlet containers
  • APIs related to Java EE
  • The future of Java EE / Jakarta EE

Jakarta EE provides the opportunity to revitalise and modernise Java EE, but in order to do that it's more important than ever that we know what matters to all of its users out there.

We started the survey the 15th of March, 2018. Unfortunately a small barrage of other surveys would soon follow, among others the Eclipse Jakarta EE Survey, the Jakarta EE Logo selection, and the Baeldung survey. Despite all those other surveys going on at the same time we still managed to get 1054 respondents. Not as much as we hoped for, but still enough to have some idea of what's important to the community.

It must be noted that OmniFaces is a JSF utility library, so the public we attract is naturally more interested in JSF than the primary public of the many parallel surveys that were going on. We did track where the respondents originated from, and 344 of them took the survey directly on the omnifaces.org website.

It must also be disclosed that one of the OmniFaces members (the writer, Arjan), works for Payara. Payara however was in no way involved with either the creation of the survey or the report. Payara did tweet about the survey a couple of times.

Let's take a look at the outcome now.

 

Question 1 - Which versions of Java EE have you (historically) used?

This question was about which version of Java EE people have ever used, and hopefully will give us some idea of how much experience our audience has and how long they've been using Java EE.

It appears though that most of our respondents haven't used the older versions so much. Far less than half of the respondents has ever used Java EE 5. On the other hand, there's still a relatively big proportion of respondents that have used the precursor technologies of Java EE (the ones older than J2EE 1.2).

< J2EE 1.2J2EE 1.2J2EE 1.3J2EE 1.4Java EE 5Java EE 6Java EE 7Java EE 80%10%20%30%40%50%60%70%80%90%5%10%12%23%38%63%81%34%

 

Question 2 - Which versions of Java EE have you recently (last couple of months) used?

Looking at what people have recently been working on we see that J2EE 1.3 and J2EE 1.4 is almost non-existent. The response for those is well within the error margin. There's still a number of people working on Java EE 5 applications though, which is now more than a decade old! Not surprisingly, most people are working with Java EE 7, for which all currently active vendors have a supported version out.

Maybe somewhat surprisingly is that 36% of the respondents are already using Java EE 8, given that not all vendors have a fully supported version out or have even implemented all Java EE 8 APIs yet. Of course, this can also mean respondents are using parts of Java EE 8. WildFly 12 for instance supports most Java EE 8 APIs, except for EE Security (which will come in WildFly 13).

 

Question 3 - Which application servers have you recently used?

Looking at which (Java EE) application servers are most frequently used there's a very clear winner, and that's RedHat's WildFly. More than half of the respondents have recently used this server. Trailing a good deal behind at the second place is Oracle's GlassFish. Despite being largely abandoned by Oracle and not supported, still 37% of responds use this. Payara Server and TomEE share the third place.

A slew of servers had so few respondents that taking the error margin into account qualifies them as practically unused by our respondents. This included Geronimo, the once promising server from Apache that silently and without any notice stopped, Resin, a very promising Web Profile implementation back then with its own CDI implementation (CanDI), which however never managed to get passed Java EE 6, and JOnAS, the mostly French server which had a number of its own unique component implementations as well, but like Geronimo just silently stopped at some point. Following is a number of mostly Korean, Japanese and Chinese servers. These servers are mostly used in their respective countries, and seemingly English language surveys are not (much) picked up by the users of these servers.

 

Question 4 - How would you rate the application servers that you've used?

For this question respondents could rate the servers they've used using 5 categories. There were two negative ones: "Hate it" and "Don't like it", a neutral one: "It does the job, but that's all", and two positive ones "Like it" and "Love it". The outcome has different aspects that we'll be looking at individually. Note that the servers that weren't effectively used by anyone are left out.

Love it

The first aspect we'll be looking at is a ranking of all servers that got the maximum appreciation: "Love it". Here we see Payara Server is the winner. Almost half of the people who used Payara said they loved it. At the second place we see WildFly again, where over a third of the respondents who use WildFly said they loved it. Do note that since WildFly is used much more than Payara Server, in absolute numbers more respondents from this survey loved WildFly. Statistics can be a tricky thing.

Quite interesting is that Liberty is relatively much loved and enters at the third place. Liberty is IBM's still relatively new server that does many things right compared to its older sibling WebSphere. Also interesting to see is the stark difference in love between Payara Server and GlassFish. Payara Server is directly based on GlassFish, but with many extra bug fixes and features.

Like it

In the "Like it" category we see WildFly and JBoss EAP topping the chart. Note that these too are largely the same server, with JBoss EAP essentially a kind of "LTS" of a specific WildFly version with the option to get a support subscription and extra bug fixes. With the exception of WebLogic and WebSphere, the servers are quite close together in this category.

Hate it

Skipping the neutral and dislike categories (they'll be included in the final score though), let's take a look at the hate category. Overal we see that there's relatively little hate among the respondents. Liberty, JBoss EAP, TomEE, GlassFish, Payara Server and WildFly all have very small percentages of hate. The only real exception is WebSphere here, and to a lesser degree WebLogic. In the case of WebSphere, it's perhaps not a surprise. Only its installer is already larger than many complete servers (around the 100MB), and it downloads in excess of 2GB of "stuff". Even in 2018 that's still excessive. After that an actual server needs to be created taking another 200MB or so. This and a number of other issues (e.g. not being able to run on macOS) doesn't make it much popular. Of course IBM recognised this long ago, and all new development is on Liberty, which is essentially everything that WebSphere is not.

Total score

For the total score we used a weighted sum, with the weights (factors) being -3 for "Hate it", -2 for "Don't like it", 1 for "It does the job, but that's all", 2 for "Like it" and 3 for "Love it". For this total score we see Payara Server still wins, but now it's only a small margin with WildFly, which is very close. This seems mainly attributed to WildFly having many more points in the "Like it" category. In the next group we see Liberty, TomEE, JBoss EAP and GlassFish all scoring quite close to each other. All the way at bottom we find WebLogic and WebSphere. WebLogic just about manages to get a positive score, but WebSphere's is deeply negative.

 

Question 5 - Which Java EE APIs have you used recently?

When looking at the Java EE APIs that people use most, JPA is the overal winner. This is interesting, since in recent years efforts for the JPA spec have been minimised, even to the point that one not rarely hears that JPA is "done" and people have moved on to e.g. MongoDB. Looking at the outcome of this survey this doesn't seem to be exactly the case. CDI follows close and lands at the second place. This is probably no surprise, as since its inception in 2009 CDI has rapidly increased in performance and is now for many cases the default type of bean to use.

Initially somewhat surprising is JSF scoring so high here, and landing just above JAX-RS at the 3rd place. This is surprising since there's a quite vocal community out there proclaiming the era of server side rendering frameworks has come to an end, and the future belongs to the client. For obvious reasons we at OmniFaces don't fully agree with that, but we're also not entirely blind to the fact that the client has indeed taken a large bite out of the total web framework market. As mentioned in the beginning of this article, OmniFaces is a JSF utility library, so our audience likely has a more than average amount of JSF users among it.

Truly surprising though is the high score of EJB, which is often cited as having its name tainted by the complexities of EJB 2 and never quite recovered. Even though EJB 3 is very usable, in Java EE 7 and above CDI can be used instead for quite a lot of cases. It could of course be that EJB is only used for a few small things such as its timer service, but this would need more research and possibly a follow-up survey to really get clear.

Java EE Security, a new spec in Java EE 8, is already used by 24% of the respondents. Given its young age this is quite a good outcome. JASPIC and JACC are both at the very bottom, but these APIs (SPIs actually) are not really aimed at application developers. They are used by higher level frameworks and vendors, e.g. the Java EE Security API strongly builds on JASPIC and will likely build more on JACC in a future release. So these APIs are being used, but just not directly by application developers. A somewhat similar thing also holds for JTA, which is mostly used under the covers by JPA and EJB, but is effectively used directly with the relatively new @Transactional and @TransactionScoped annotations.

 

Question 6 - Have you used a (standalone) Servlet container recently?

A standalone Servlet container is a server that supports at least the Servlet spec, and typically a number of strongly related specs such as the Servlet Container Profile of JASPIC (not full JASPIC), Expression Language, JNDI, JSP and WebSocket.

As it appears, about the half of the respondents have used such Servlet container, while the other half hasn't (and thus only used a full or web profile Java EE server).

 

Question 7 - Which Servlet containers have you used recently?

From the people who have used a Servlet container, the overwhelming majority used at least Tomcat. At 85% Tomcat largely dominates this segment. Still, 29% and 22% for Jetty and Undertow are nothing to sneeze at either, and seemingly a non-trivial amount of respondents use either Jetty or Undertow next to Tomcat (people could choose multiple servers).

Undertow's 22% is particularly impressive, as Undertow is not so much known as a standalone Servlet container but more as the Servlet container that Jboss EAP/WildFly uses. It's also relatively new, especially when compared to Tomcat and Jetty which both have existed since the dawn of times.

The "other" category was perhaps not entirely understood, as most respondents choosing this entered products that actually weren't standalone Servlet containers. WebLogic, GlassFish, Liberty and Payara certainly aren't. Grizzly and Netty come closer, but they actually are more akin to HTTP engines, and are themselves not Servlet compatible.

Other

 

Question 8 - Which additional Java EE libraries do you use with your Servlet container?

This question asked specifically about the Java EE libraries that people add to their Servlet containers. Java EE libraries here means an implementation of a Java EE spec, such as JPA and CDI, but not e.g. Guave, Spring, etc.

Consistent with the API usage outcome, JPA is added most often to a standalone Servlet container, followed by JSF, JAX-RS, Bean Validation and CDI. In this particular question though it was asked which exact implementation people add. As can be seen Hibernate wins hands down over EclipseLink (25%) and OpenJPA (7%). Likewise Mojarra (46%) wins over MyFaces (15%) and Jersey (45%) wins over RESTEasy (28%) and CFX (17%).

The EE Security API has only one standalone implementation yet, which is Soteria (there's another implementation by IBM, but it's embedded in Liberty and not suitable for standalone use). This one is quite new and only used by a couple of people, but it's nevertheless interesting that it is being used standalone.

The "Other" category wasn't entirely understood however. The idea was for other implementations of Java EE specs to be listed here, like e.g. Wink for JAX-RS, HornetQ, OpenMQ or JORAM for JMS, Narayana or JOTM for JTA, etc. None of these were mentioned though, and instead PrimeFaces, OmniFaces, DeltaSpike and Spring were mentioned, which aren't implementations of Java EE specs. Here it's probably the wording of the survey question that's to blame. One respondent did mention DataNucleus though, which is a JPA implementation, and suggested that the question is biased against it by not mentioning it. Given the importance of JPA this is indeed true, so we'll make sure to include DataNucleus next year.

Other

 

Question 9 - Have you used MicroProfile APIs recently?

MicroProfile is an industry effort to bring extra APIs into the EE fold for things which Java EE doesn't have an API now, such as configuration and metrics. At the same time MicroProfile is also a profile like WebProfile, where only those extra APIs are included as well as JAX-RS and CDI.

Despite all Java EE vendors, with the exception of Oracle, offering those extra APIs with their products, and some implementations being able to be used standalone as well, usage among the respondents was quite low. Only a little more over 15% said to have used MicroProfile APIs recently.

This may have to do with all of those APIs being still very young and haven't established themselves yet. Another reason could be that most vendors by default promote MicroProfile as its own isolated product and not as an extra set of APIs to be used together with the main Java EE ones (Payara is the only notable exception here). As most people would use for example the regular WildFly server (as opposed to the spin-off product WildFly Swarm), which doesn't have the MicroProfile APIs out of the box, this could be a potential barrier.

 

Question 10 - Which MicroProfile products have you used recently?

Looking at which server product those relatively few people that use MicroProfile APIs use it's again WildFly that tops the charts here, with more than 50% of respondents using this variation of the WildFly main server. Payara Micro follows closely with 45%. Compared to the (Java EE) server product the gap between WildFly and Payara is much smaller here. Payara also has all the MicroProfile APIs included out of the box with the EE Server product, and in this variation Liberty and Payara are used exactly as much. There are various other MicroProfile products, but they are not (yet) so popular (specifically when taking into account only a small proportion of respondents said to be using MicroProfile in the first place)

Seeing that Payara Micro is more used for MicroProfile APIs than Payara Server, one may come to the conclusion that the fact that most MicroProfile vendors don't support these APIs out of the box on their server product doesn't matter that much. While this may be true, it could also be that many users aren't quite aware Payara Server supports these APIs.

 

Question 11 - Which MicroProfile APIs have you used recently?

Config was the first MicroProfile API and arguably one of the APIs that's most missed in Java EE. A Java EE Configuration API was in the works, but it never materialised. It's perhaps no surprise that config is thus the most used API from the MicroProfile. Health, Metrics and JWT Authentication follow with some distance. Open API, Open Tracing and the Type-safe rest client are all quite new and haven't been implemented by all vendors yet, so it's not a big surprise these aren't used that much yet.

 

Question 12 - Which Java EE specific extension libraries have you used recently?

This question was specifically about Java EE extension libraries, meaning libraries that one can only use with Java EE. This mostly means libraries that extend or are plug-ins for JSF, CDI, JCA, etc. PrimeFaces is the clear winner here, followed with some distance by OmniFaces (but keep the bias in account, since the survey was promoted via the OmniFaces account and website). Given the popularity that Seam once had, and DeltaSpike being its spiritual successor, just over 20% feels a bit on the low side. DeltaSpike is certainly worth looking at though. Once one of the most frequently used JSF component libraries, RichFaces after being sunset by Red Hat has been reduced to only 13% usage, while newcomer BootsFaces has climbed up to that same percentage.

As far as the "Other" response goes, "MyFaces" was mentioned a lot, but this of course isn't a Java EE Extension library, but a Java EE Implementation library (it implements JSF, as mentioned in a previous question). Tobago, ButterFaces, IceFaces and PrettyFaces are indeed all Java EE extension libraries. Oracle ADF is too, although this is a somewhat specific one (it practically only really works on WebLogic). It's a question if one can really count Spring as a Java EE extension framework. Technically it is, but at the same time it mostly positions itself as an independent full stack framework.

So again, for next year we could do with an explicit definition of "Java EE specific extension library".

Other

 

Question 13 - Which APIs would you most like to see updated in the next version of Java EE (Jakarta EE)?

When asked which API (spec) people like to see updated, a natural instinct might be to say "all of them". Perhaps not including the ones they hate, or maybe even those so that they can be hated a little less. With only a finite amount of resources this is not always an option, so that's why this question specifically asks respondents to rank the available APIs.

We take a look at the results in three different ways; the amount of people who put an API on the number one position, the amount of people who put an API on the number two position, and finally the total weighted score per API.

APIs at number 1 of the ranking

As can be seen none of the APIs had a really absolute majority. The highest score here was JSF with just over 20%. The question is, did JSF score so (relatively) high here because the potential bias, or do many people see JSF as something that has potential but *really* could do with some desperately needed improvements? CDI and JPA are high on this list too, which matches the outcome of which APIs people use most. Java EE Security is somewhat of an outlier. Being a new spec in Java EE 8 it isn't used that much yet, but already people want to see it improved. As a side-note, Java EE Security 1.0 could only address some of the basics (the low hanging fruit). More was planned for 1.0, but a lack of resources prevented many of those other planned things (such as security interceptors, evens and custom authorization rules) to be actually included.

APIs at number 2 of the ranking

In the number 2 list we see some more variety in the category of APIs having more than 2% of the respondents choosing them, although we do largely see the same APIs again in the top tier. CDI now takes the lead, moving up one place from the number 1 list, and JAX-RS moves up 3 places. JPA is again at number 3, while JSF is at 4 now.

Total score

When we take a look at the total score, we see that the top tier is formed of JPA, CDI and JAX-RS, which is basically identical to the top tier of question 5, which asked what APIs people have used recently. Clearly, people like to see APIs that they actually use improve. In the total score ranking too, EE Security is the exception. It lands on the 4th place, just an inch away from JAX-RS. Interestingly though, JASPIC and JACC end at the last places. As mentioned above, it's likely not common knowledge that these two APIs are the foundation of EE Security.

JavaMail and JDNI are both two examples of APIs that are used more than that people want to have them improved. Likely they just do the job (sending mails resp. looking up resources) and people don't see much need for further improvements there.

 

Question 14 - What do you think about these options to improve Java EE / Jakarta EE?

This question asked for a variety of broad, somewhat cross-cutting concerns to improve Java EE overall (the potentially improved Java EE will be called Jakarta EE then). The choices with their keys in the graph were:

  • CDI rebase - Rebase most Java EE APIs on CDI (remove JSF @ManagedBeans, remove JAX-RS @Context, ...)
  • Remove deprecated - Aggressively remove everything that is already @Deprecated (e.g. getServlet() in ServletContext)
  • Deprecate legacy - Aggressively deprecate and remove legacy features (e.g. JSP support in JSF)
  • Add MP APIs - Add equivalents of some or all MicroProfile APIs to Java EE (e.g. Config, JWT, ...)
  • Deployment models - Officially add alternative deployment models (Uberjar, run .war from command line, etc)
  • Add JCache - Add JCache to Java EE so that both applications and internal components (such as JPA) can use it
  • Rebase on Concurrency - Rebase most Java EE APIs that use threading to use Concurrency Utils thread pools
  • Cloud connectors - Add more connectors to cloud services (e.g. Amazon SQS, MQTT, Apache Kafka)
  • Security connectors - Add more connectors to security services (e.g. OAuth2, SAML, OpenID, Yubikey)

We'll be looking at two graphs for this one; the one which shows the options for which respondents choose "Please do this!", and the one with the weighted outcome (using the same weights as in question 4).

Please do this!

Of all the options presented, rebasing most Java EE APIs on CDI is the one that most people really want to see. It's followed closely by more security connectors (authentication mechanisms). Clearly the ones that currently ship by default with Java EE, namely FORM (+ custom form), BASIC, DIGEST and CERT aren't enough anymore. MicroProfile recognised this too and therefor added a JWT authentication mechanism as one of the initial new APIs.

Weighted score

When looking at the weighted score, we see that all options presented have community support. Security connectors though have the most support, followed with some distance by adding JCache. Rebasing on CDI and Concurrency Utils, which could indirectly be taken as a wish to have a better integrated platform, has much support as well. At the bottom of the graph we see "Remove deprecated" and "Deprecate legacy". Seemingly people support removing some of the cruft that's in Java EE, but they are not overly concerned about this.

It's interesting to see that the alternative "Deployment models", which according to some vocal voices is *the* reason Java EE has been losing ground (the AS model is allegedly outdated), doesn't bother our respondents that much either. A reason is perhaps that with popular tools such as docker it doesn't matter so much whether you put an AS in it, or an uberjar. The AS might be known outside Java EE as a super large monolith, but actual Java EE users probably know that a modern AS is ~70 to 100mb and starts between 1 and about 3 seconds, while an uberjar can easily be around that same size too and starts in about the same time as well.

 

Question 15 - Do you have any final comments on how Java EE / Jakarta EE can be improved in the future?

The final question was a fully open question where people could comment whatever they wanted. 179 respondents left a comment, which is about 16% of the total number of respondents. Overal the quality of the comments was quite good. We'll provide a few of them here:

"Take good care of it, don't leave legacy behind. But still move it forward. by all means remove already deprecated stuff. I feel things can often be don the old and the new way.. And the support forums are full of good recomendations on both old and new. And it's sometimes confusing not being an expert."

"Please, single set of bean annotations. Not mixture of CDI, EJB and JSF"

"Externalize configuration for both AS domain and the app for all configurable properties. - All AS settings must be configurable via command line."

"Make it easier to have something between a full application server and just a few features (i.e. I only need JSF, JAX-WS, JavaMail, and DB, but not JPA and EJB, etc.) so they don't have to be manually added in the app or grafted into the servlet container in some non-standard way. Also, I'd prefer to be able to easily choose which technologies (JSF: Mojarra vs MyFaces, JAX-WS: Metro vs Apache CXF, etc.). Just a general thing to watch out for: Don't assume all users will want to use Maven; be sure you provide another way to download."

Tag cloud

Estimations are easy!

$
0
0
Now for something a little different on this blog, though still in the domain of development. Today we're introducing "The OmniDevs", a comic strip dedicated to our daily struggles as developers in this exciting, but at times crazy, place we call the software industry.

Without further ado, let's kick off with the first episode which is about the "favourite" pastime of most devs out there: estimating our work! (click on the image for a larger version)

Stay tuned for the next instalment!

The productive standup

$
0
0
Timeboxing is a very simple technique to manage time and become more productive. Our OmniDevs have honed this technique to perfection!

Here they are in their daily standup with scrum master Robert:(click on the image for a larger version)

Stay tuned for the next instalment!

Jan 2020 update: Piranha Micro getting more compatible

$
0
0
We're currently hard at work with our Piranha runtime implementation. Piranha is a new Jakarta EE and MicroProfile runtime build from scratch. A distinguishing feature is that it's build from the ground up to use Jakarta EE and MicroProfile as a framework, which means without any (application) server bits. This is essentially how you would use a mock framework for Jakarta EE, except that with Piranha it's the actual runtime.

Piranha Micro takes the framework bits and with a minimal amount of glue code assembles these into what resembles a more traditional Jakarta EE Server (including an HTTP stack and the ability to run a single war archive). We'll be blogging about some interesting features this version of Piranha has soon. For now just a small status update, and that's that we're working hard on compatibility.

Last month we passed the MicroProfile JWT TCK (which infers a certain minimal level of compatibility with CDI, Jakarta REST and MicroProfile Config). This month we've been looking at the Java EE 7 samples suite. This is an older, but still very valuable resource to both test implementations and learn how to use the Jakarta EE (Java EE) APIs.

We're happy to announce that Piranha Micro is passing all of the appropriate JASPIC (Jakarta Authentication) tests, and a large number of the Servlet and JAX-RS (Jakarta REST) ones. The JASPIC ones are particularly nice to pass, since Piranha uses the (largely) new OmniFaces implementation called Eleos for this. Furthermore, the plain Servlet Security tests are under the hood powered by Eclipse Soteria which is a compatible implementation (CI) of Jakarta Security. To the best of our knowledge, this is another unique feature of Piranha (more about this in a later blog). Note that skipped tests for JASPIC are about EJB, which Piranha doesn't support yet.

The results from running Java EE 7 samples against the latest snapshot from master (20.1.0-SNAPSHOT) are shown below:


[INFO] Reactor Summary for Java EE 7 Sample: jaspic 1.0-SNAPSHOT:
[INFO]
[INFO] Java EE 7 Sample: jaspic - common .................. SUCCESS [ 1.044 s]
[INFO] Java EE 7 Sample: jaspic ........................... SUCCESS [ 0.284 s]
[INFO] Java EE 7 Sample: jaspic - basic-authentication .... SUCCESS [ 7.600 s]
[INFO] Java EE 7 Sample: jaspic - custom principal ........ SUCCESS [ 7.132 s]
[INFO] Java EE 7 Sample: jaspic - programmatic-authentication SUCCESS [ 4.075 s]
[INFO] Java EE 7 Sample: jaspic - lifecycle ............... SUCCESS [ 5.602 s]
[INFO] Java EE 7 Sample: jaspic - wrapping ................ SUCCESS [ 4.041 s]
[INFO] Java EE 7 Sample: jaspic - register-session ........ SUCCESS [ 5.756 s]
[INFO] Java EE 7 Sample: jaspic - async-authentication .... SUCCESS [ 0.272 s]
[INFO] Java EE 7 Sample: jaspic - Status codes ............ SUCCESS [ 5.535 s]
[INFO] Java EE 7 Sample: jaspic - dispatching ............. SUCCESS [ 5.546 s]
[INFO] Java EE 7 Sample: jaspic - dispatching JSF CDI ..... SUCCESS [ 4.076 s]
[INFO] Java EE 7 Sample: jaspic - ejb-propagation ......... SKIPPED [ 0.290 s]
[INFO] Java EE 7 Sample: jaspic - ejb-register-session .... SKIPPED [ 0.238 s]
[INFO] Java EE 7 Sample: jaspic - jacc-propagation ........ SUCCESS [ 5.495 s]
[INFO] Java EE 7 Sample: jaspic - invoke EJB and CDI ...... SKIPPED [ 0.228 s]
[INFO] ------------------------------------------------------------------------

[INFO] Reactor Summary for Java EE 7 Sample: servlet 1.0-SNAPSHOT:
[INFO]
[INFO] Java EE 7 Sample: servlet .......................... SUCCESS [ 0.754 s]
[INFO] Java EE 7 Sample: servlet - simple-servlet ......... SUCCESS [ 5.634 s]
[INFO] Java EE 7 Sample: servlet - async-servlet .......... SUCCESS [ 0.215 s]
[INFO] Java EE 7 Sample: servlet - servlet-filters ........ SUCCESS [ 3.674 s]
[INFO] Java EE 7 Sample: servlet - cookies ................ SUCCESS [ 4.096 s]
[INFO] Java EE 7 Sample: servlet - error-mapping .......... SUCCESS [ 4.037 s]
[INFO] Java EE 7 Sample: servlet - event-listeners ........ SUCCESS [ 4.178 s]
[INFO] Java EE 7 Sample: servlet - metadata-complete ...... SUCCESS [ 3.986 s]
[INFO] Java EE 7 Sample: servlet - web-fragment ........... SUCCESS [ 0.147 s]
[INFO] Java EE 7 Sample: servlet - nonblocking ............ SUCCESS [ 0.174 s]
[INFO] Java EE 7 Sample: servlet - protocol-handler ....... FAILURE [ 13.564 s]
[INFO] Java EE 7 Sample: servlet - resource-packaging ..... FAILURE [ 1.939 s]
[INFO] Java EE 7 Sample: servlet - file-upload ............ SUCCESS [ 3.205 s]
[INFO] Java EE 7 Sample: servlet - programmatic-registration SUCCESS [ 3.977 s]
[INFO] Java EE 7 Sample: servlet - security-basicauth ..... SUCCESS [ 4.037 s]
[INFO] Java EE 7 Sample: servlet - security-digest ........ SKIPPED [ 0.283 s]
[INFO] Java EE 7 Sample: servlet - security-form-based .... SUCCESS [ 4.133 s]
[INFO] Java EE 7 Sample: servlet - security-clientcert .... SKIPPED [ 0.394 s]
[INFO] Java EE 7 Sample: servlet - security-clientcert-jce SKIPPED [ 0.395 s]
[INFO] Java EE 7 Sample: servlet - security-programmatic .. SUCCESS [ 4.084 s]
[INFO] Java EE 7 Sample: servlet - security-deny-uncovered SUCCESS [ 3.997 s]
[INFO] Java EE 7 Sample: servlet - security-allow-uncovered SUCCESS [ 3.998 s]
[INFO] Java EE 7 Sample: servlet - security-annotated ..... FAILURE [ 3.975 s]
[INFO] Java EE 7 Sample: servlet - security-basicauth-omission SUCCESS [ 4.000 s]
[INFO] ------------------------------------------------------------------------

[INFO] Reactor Summary for Java EE 7 Sample: jaxrs 1.0-SNAPSHOT:
[INFO]
[INFO] Java EE 7 Sample: jaxrs ............................ SUCCESS [ 0.557 s]
[INFO] Java EE 7 Sample: jaxrs - async-client ............. SUCCESS [ 5.177 s]
[INFO] Java EE 7 Sample: jaxrs - async-server ............. FAILURE [ 4.058 s]
[INFO] Java EE 7 Sample: jaxrs - beanvalidation ........... FAILURE [ 4.178 s]
[INFO] Java EE 7 Sample: jaxrs - beanparam ................ SUCCESS [ 4.105 s]
[INFO] Java EE 7 Sample: jaxrs - client-negotiation ....... FAILURE [ 4.240 s]
[INFO] Java EE 7 Sample: jaxrs - db-access ................ FAILURE [ 3.567 s]
[INFO] Java EE 7 Sample: jaxrs - dynamicfilter ............ SUCCESS [ 4.885 s]
[INFO] Java EE 7 Sample: jaxrs - fileupload ............... SUCCESS [ 4.671 s]
[INFO] Java EE 7 Sample: jaxrs - filter ................... SUCCESS [ 4.226 s]
[INFO] Java EE 7 Sample: jaxrs - filter-interceptor ....... SUCCESS [ 0.186 s]
[INFO] Java EE 7 Sample: jaxrs - interceptor .............. SUCCESS [ 0.163 s]
[INFO] Java EE 7 Sample: jaxrs - invocation ............... SUCCESS [ 0.149 s]
[INFO] Java EE 7 Sample: jaxrs - invocation-async ......... SUCCESS [ 0.169 s]
[INFO] Java EE 7 Sample: jaxrs - jaxrs-client ............. FAILURE [ 4.458 s]
[INFO] Java EE 7 Sample: jaxrs - jaxrs-endpoint ........... SUCCESS [ 4.332 s]
[INFO] Java EE 7 Sample: jaxrs - jsonp .................... SUCCESS [ 4.377 s]
[INFO] Java EE 7 Sample: jaxrs - link ..................... SUCCESS [ 0.268 s]
[INFO] Java EE 7 Sample: jaxrs - mapping-exceptions ....... SUCCESS [ 4.113 s]
[INFO] Java EE 7 Sample: jaxrs - paramconverter ........... SUCCESS [ 4.300 s]
[INFO] Java EE 7 Sample: jaxrs - readerwriter ............. SUCCESS [ 4.483 s]
[INFO] Java EE 7 Sample: jaxrs - readerwriter-json ........ SUCCESS [ 0.204 s]
[INFO] Java EE 7 Sample: jaxrs - request-binding .......... SUCCESS [ 0.149 s]
[INFO] Java EE 7 Sample: jaxrs - resource-validation ...... FAILURE [ 4.474 s]
[INFO] Java EE 7 Sample: jaxrs - server-negotiation ....... FAILURE [ 4.112 s]
[INFO] Java EE 7 Sample: jaxrs - simple-get ............... SUCCESS [ 3.982 s]
[INFO] Java EE 7 Sample: jaxrs - singleton ................ SUCCESS [ 5.907 s]
[INFO] Java EE 7 Sample: jaxrs - readerwriter-injection ... FAILURE [ 2.542 s]
[INFO] Java EE 7 Sample: jaxrs - jaxrs-security-declarative SUCCESS [ 4.497 s]
[INFO] ------------------------------------------------------------------------

Arjan Tijms

Piranha 20.1.2 released!

$
0
0
Piranha 20.1.2 has been released :)

In total 59 issues were done for this release, which mostly included work for Piranha Micro, but also includes improvements for Servlet compatibility among others. Note that Piranha is a work in progress and not yet ready for regular use, let alone production usage.

Piranha itself is an upcoming Jakarta EE and MicroProfile runtime, currently in its early stages of development. Piranha's main goal is to use Jakarta APIs as much as possible as a library, using a flat class loader, and no concept of deploying applications, in other words without being an application server.

Piranha Micro however builds on the core Piranha foundation to deliver something that comes closer to a server; it can run a single application in archive form, albeit it can't undeploy and redeploy (this is on purpose). Specifically for embedded use it features an isolated class loader. Contrary to a traditional application server where an isolating class loader is used to run multiple applications in separation from each other, its purpose in Piranha is to isolate the archive from the application and all its classes and config files that embeds Piranha.

The jar files with Jakarta EE APIs and their implementations (for example the Jakarta Faces API and the Mojarra implementation) are handled in a somewhat unique way in Piranha Micro. The native method it internally uses is to load these via Maven, as demonstrated by the following snippet of internal code:

// Resolve all the dependencies that make up a Piranha runtime configuration

ConfigurableMavenResolverSystem mavenResolver = Maven.configureResolver();

configuration.getRepositoriesList().stream().forEach(repoUrl ->
mavenResolver.withRemoteRepo(createRepo(repoUrl)));

JavaArchive[] piranhaArchives =
mavenResolver
.workOffline(configuration.isOffline())
.resolve(configuration.getMergedDependencies())
.withTransitivity()
.as(JavaArchive.class);

// Make all those dependencies available to the Piranha class loader
ClassLoader piranhaClassLoader = getPiranhaClassLoader(piranhaArchives);

This means Piranha Micro is very flexible where it loads its own jars from. They can come from Maven central, an alternative remote repo, a local repo on the filesystem, the local .m2, etc. In Piranha 20.1.2 just a single Uber-jar is downloaded this way, but we'll refine this in the coming versions.

A related feature of Piranha is that jars loaded this way do not need to be stored and/or extracted on the filesystem first, but are loaded in-memory and directly passed to the custom class loader. Piranha Micro uses ShrinkWrap archives for this, which has the additional advantages that when archives are created programmatically for embedded usage, Piranha Micro can run these directly.

Due to the early stage of development, Piranha Micro is currently only readily available via its Maven Arquillian connector. It can be seen in action in the Java EE 7 Samples project. For instance by cloning the project and typing the following:


cd jaspic
mvn clean install -Ppiranha-embedded-micro

Arjan Tijms

Viewing all 76 articles
Browse latest View live