Friday, 31 October 2014

getAsModifableSet()

At work we have taken great care to limit access to a Set of values, as elements of the set have constraints between each other, that need to be sustained.

So any call to retrieve a set, is always done using Collections.unmodifiableSet.

public Set<T> getCycles() 
{
  return Collections.unmodifiableSet(cycles);
}

I would have been much more at ease, if we had also decided to make the elements of the set Immutable Objects, but alas, this is the status quo.

As it is right now, it's possible to change the attributes of the individual elements, and so break the constraints between them.

Surprise

Imagine the surprise of my colleague, when, out of nowhere, he found the following method:
public abstract SortedSet<T> getAsModifableSet();

The typo in the name is actually in the code, I swear! My grasp of the intricacies of spelling is beyond reproach.

And it returns a very implementation-specific Set as well.

And it's public too.

I'm sure there are always good reasons for these things, but sometimes I'd like to run my head into a wall.

Sunday, 26 October 2014

Covariant return type

“In object-oriented programming, a covariant return type of a method is one that can be replaced by a "narrower" type when the method is overridden in a subclass.”

Since JDK 5.0 it is possible to provide covariant return types in methods of subclasses.[2] Before this release, the Java programming language was invariant with regard to method return types.

Unfortunately, covariance is not possible with method parameters. If you wish to use that, reference [1] has a good explanation of how to do this using Generics.

Example

Scala

In Scala all three are possible, contravariant, covariant and invariant for both method parameters as well as method return types. It is used fairly frequently.

For more information, the blog in [3] has some excellent explanation.

References

[1] Covariant Parameter Types
https://www.java-tips.org/java-se-tips-100019/24-java-lang/482-covariant-parameter-types.html
[2] Wikipedia - Covariant return type
http://en.wikipedia.org/wiki/Covariant_return_type
[3] Atlassian Blogs - Covariance and Contravariance in Scala
http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/

Sunday, 19 October 2014

Glassfish Security Realms

The JDBCRealm

In the Glassfish Administration Console, go to Configurations -> server-config -> Security -> Realms -> and select "New".

We're going to choose com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm.

The jaas.context name of the new realm is "jdbcRealm".

A jdbcRealm needs both a user table and a group table. The group table should store both userids as well as groupids. In other words,
  • the group table doesn't only contain groups, and
  • has a composite primary key, consisting of userid and groupid.

Database Schema

The user table is called "mm_admin" in my case, and the groups table is called "mm_admin_mm_groups".

I have created the "mm_groups" table to store extra information for groups, but that table is ignored by the jdbcRealm.

Some serious disadvantages of the jdbcRealm are:
  • groups are cached, which means if a user changes groups, the Glassfish Server needs to be rebooted.
  • flexibility is about zero, for instance if I have an expiration date attached to my usertable, I'm out of luck.
All this causes me to look elsewhere, namely towards the flexibleJDBCRealm5

The flexibleJDBCRealm

The great advantage of the flexibleJDBCRealm is that you can add SQL queries that are run to retrieve passwords and groups.

Instructions

Well, according to instructions found here6, you have to:
  1. download the flexiblejdbcrealm-deploy-1.2-all.jar
  2. put it into glassfish/domains/domain1/lib directory
  3. change glassfish/domains/domain1/config/login.conf to add
    flexibleJdbcRealm {
    org.wamblee.glassfish.auth.FlexibleJdbcLoginModule required;
    };
  4. reboot the glassfish
  5. In the Glassfish Administration Console, go to Configurations -> server-config -> Security -> Realms -> and select "New"
  6. enter the class name org.wamblee.glassfish.auth.FlexibleJdbcRealm
  7. set the properties, for example like in the image above.

Properties

The properties that can be entered could use a little more explaining compared to what is available at [6].
password.digest
uses MessageDigest(String algorithm). Possible values are "PLAIN", "MD2", "MD5", "SHA-1", "SHA-256", "SHA-384" and SHA-512.
password.encoding
the encoding, I find HEX to be the most useful. Possibile values are "TEXT", "HEX" and "BASE64". A variation of "HEX" is "HEX:<digits>", for example "HEX:40". This padds the beginning of the encoding with zeros to reach the length required. For example MySQL itself always creates passwords using the SHA() function to 40 hex digits also padding the beginning with zeros.
sql.groups
select groupid from mm_admin_mm_groups where name in (?)
sql.password
select passwd from mm_admin where name in (?) and validuntil > now()
jaas.context
flexibleJdbcRealm
datasource.jndi
of course, the connection string to the database
NOTE: he's complaining about setting properties in the realm with a = in them. So I had to go back to an "in (?)" construction for the SQL queries.

Logging

In glassfish/domains/domain1/config/logging.properties, add: org.wamblee.level=FINEST.

Application Configuration

My web.xml would look like thusly:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" 
    xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">

    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <security-constraint>
        <display-name>Administration</display-name>
        <web-resource-collection>
            <web-resource-name>Administration REST Resources</web-resource-name>
            <description/>
            <url-pattern>/resources/administration/*</url-pattern>
            <url-pattern>/administration/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <description/>
            <role-name>deputy</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>deputyRealm</realm-name>
    </login-config>
    <security-role>
        <description/>
        <role-name>deputy</role-name>
    </security-role>
</web-app>
My glassfish-web.xml looks like:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app 
    PUBLIC 
    "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" 
    "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">

<glassfish-web-app error-url="">
  <security-role-mapping>
    <role-name>deputy</role-name>
    <group-name>deputy</group-name>
  </security-role-mapping>
  <class-loader delegate="true"/>
  <jsp-config>
    <property name="keepgenerated" value="true">
      <description>Keep a copy of the generated servlet class' java code.</description>
    </property>
  </jsp-config>
</glassfish-web-app>
In this file you can create a mapping between security roles and groups.

Declarative Security

An example of declarative security using Annotations:
@DeclareRoles("deputy")
@RolesAllowed("deputy")
@Stateless
@Path("/administration/worldattributes")
public class WorldattributesBean extends AbstractFacade<Worldattribute>
{
This means the role definition in the web.xml can be removed.

In the example above, the security role is applied to the entire Bean, so for each method in the bean, instead of on each method that requires the role.

Programmatic Security

Unfortunately, some fine-grained security can only be done with programmatic means, for example determining if a person who has authenticated themselves owns a certain object that needs mutated upon. In my example, this info in a Rest service can be obtained through a SecurityContext:
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.Context;
...
@POST
@Override
@Consumes(
{
     "application/xml""application/json"
})
public void create(Worldattribute entity, @Context SecurityContext sc)
{
  itsLog.info("create");
  final String name = sc.getUserPrincipal().getName();

FAQ

I get WEB9102: Web Login Failed: com.sun.enterprise.security.auth.login.common.LoginException: Login failed: No LoginModules configured for flexibleJdbcRealm?
You forgot to add the entry to the login.conf as specified above.

References

[1] Oracle - Security in the Java EE Platform
http://docs.oracle.com/javaee/7/tutorial/doc/security-intro.htm
[2] The Java EE 7 Tutorial
Release 7 for Java EE Platform
[3] Oracle - Using the JDBC Realm for User Authentication
http://docs.oracle.com/javaee/6/tutorial/doc/glxgo.html
[4] Understanding Web Security
http://java.dzone.com/articles/understanding-web-security
[5] FlexibleJDBCRealm
http://flexiblejdbcrealm.wamblee.org/site/
[6] Installation instructions
http://flexiblejdbcrealm.wamblee.org/site/documentation/snapshot/installation.html

Sunday, 12 October 2014

REST and Error Messages

WebApplicationException

In Java REST you can throw a WebApplicationException, which indicates that something went wrong. You can add the HTTP Status to the exception, to indicate what went wrong.
throw new WebApplicationException(Response.Status.BAD_REQUEST);
But that amount of information is in most cases too little. Sure, a HTTP Status of 404 (Not Found) is quite clear, but you'd like some more information.

Luckily, I found out that we can add an entity in the Response and add the Response to the WebApplicationException.

In fact, it is the most convenient to just create your own subclass of WebApplicationException to handle this automatically.

Your own WebApplicationException


An Error Entity

The entity that gets translated into JSON and passed over the line, in my case called ErrorDetails, can provide all the information you need.

The getResponse method is the one that creates the Response, which is used to provide the HTTP Status code and the error payload for the WebApplicationException.

The json generated looks like:

    timestamp="2014-09-21T21:34:01.831", 
    errormessage="sdsgsdgsgd was not found.", 
    stacktrace=””,
    user="sdsgsdgsgd"
}

JQuery

It just took a little effort to retrieve the ErrorDetail object from the Xqhr object in the JQuery Ajax call. This should be done during error processing, as shown in the JQuery Ajax call below.

The webError in the code above is a function to parse the JSON containing ErrorDetails object, provided below.

It parses the jqXHR.responseText, to be precise. And if a stacktrace is provided, the details are put into a HTML tag with id "warning". An 'alert' is always provided.

References

Whatever can go wrong … Error Handling and RESTful Services
http://djna.wordpress.com/2009/12/07/whatever-can-go-wrong-error-handling-and-restful-services/
RESTful API Design: what about errors?
https://blog.apigee.com/detail/restful_api_design_what_about_errors
How to get the jQuery $.ajax error response text?
http://stackoverflow.com/questions/1637019/how-to-get-the-jquery-ajax-error-response-text
Use jQuery to catch and display ASP.NET AJAX service errors
http://encosia.com/use-jquery-to-catch-and-display-aspnet-ajax-service-errors/

Sunday, 5 October 2014

Getting the Stacktrace

Found this snippet to get the stacktrace as a printable String on StackOverflow[1].
However, this only provides the stacktrace of the exception, not the possible underlying exception as well.
For that, you should look at:
Of course, if you do not wish to reinvent the wheel, there is always org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable).

Just thought I'd write this down here, I always forget how to do it.

References

[1] How can I convert a stack trace to a string?
http://stackoverflow.com/questions/1149703/how-can-i-convert-a-stack-trace-to-a-string