Sunday, February 28, 2016

Spring Boot WebJar

Spring Boot WebJar


When creating an end to end application that includes client side code and server side code, we need a full application solution that can be easily built and deployed.
The client side may be written in different frameworks – angular, backbone. Spring Boot supports all of these solutions in multiple ways.

Static Resources

The strait forward way is to copy all resources from the client code (js, html, css...) to the static folder user the resources folder (see https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot).
The problem with this solution is that we are tightly couples between the client and server code. In order to compile the server code we need to copy the client compiled code to our resources folder.
To use this solution we need to create a Jenkins job that takes the client code, compiles it (using grunt or other tools) and then takes the folder that was created and copies it to the resources folder and then compile the server code.
This is definitely not the maven way. The solution that we would want is for the client code to create an artifact for us to add as a dependency in our pom file. The solution that has become a standard is what is called a webjar (www.webjar.com).

WebJar

A webjar is a zip file with the following folder structure:
META-INF\resources\webjars\artifactId\version\
When the client requests a resource from the server, Spring Boot looks in all its resource locations for the resource. The resource locations are: resource\static, resource\public, webjars.
So far the solution looks like it works nicely. The next issue is that webjar technology is not just a server side technology. Webjars come to solve another issue on the client side. When the client needs global functionality the solution for creating modules is to use webjars. What this means is that when the client needs a resource from the server, it needs to specify the artifactId and the version so that the server can retrieve it from the webjar.
For example:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head> 
    <title>Getting Started: Serving Web Content</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script src="webjars/jquery/2.0.3/jquery.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            $('p').animate({
                fontSize: '48px'
            }, "slow");
        });
    </script>
</head>
<body>
    <p th:text="'Hello, ' + ${name} + '!'" />
</body>
</html>

As you can see the client code references a version of the modules it wants to use: "webjars/jquery/2.0.3/jquery.min.js". This might be good in most cases, but the problem is that in a lot of cases our client side is a single page solution and does not necessarily need the webjar solution (with the full artifcatId and version). What then happens is that the client requests a resource but the server cannot find it since it needs the artifactid and version to find it within the webjar. We would like the client to request a js file or html file without the prefix of the webjar and for the server to find it and return it to the client.

ResourceHandlers

To do this we need to add our own bean that will supply the lookup for resources for spring.
We are actually going to solve here two other issues that arise with single page applications and Spring Boot.
In addition to the issue that we don’t want the client code to need to reference its own webjar, we would like to have the option to have all the client resources out of our jar, so that we can upgrade the client code without recompiling the server code.
Another issue with single page applications is that the client side navigation uses the url path to do this. So if the client side moves to an admin page, it will usually add to the url “/admin”. The problem with this is that if the use now refreshes his browser, the server will get a url request with “/admin” that the server does not have.
To solve this, we need to create another configuration bean that will inherit WebMvcConfigurerAdapter.  
The default implementation of spring is to search all webjars in the application (see https://spring.io/blog/2014/01/03/utilizing-webjars-in-spring-boot):
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (!registry.hasMappingForPattern("/webjars/**")) {
        registry.addResourceHandler("/webjars/**").addResourceLocations(
                "classpath:/META-INF/resources/webjars/");
    }
    if (!registry.hasMappingForPattern("/**")) {
        registry.addResourceHandler("/**").addResourceLocations(
                RESOURCE_LOCATIONS);
    }
}

We will change this and override the addResourceHandler as follows:
override def addResourceHandlers(registry: ResourceHandlerRegistry): Unit = {

  if (!registry.hasMappingForPattern("/**")) {

    registry.addResourceHandler("/**").addResourceLocations(

      classpathResourceLocations: _*)

  }

}

This will now allow us to define a string array that will tell spring were to search for resources.
Our basic resource location array will be as follows:
private var classpathResourceLocations = List(

  "classpath:/META-INF/resources/", "classpath:/resources/",

  "classpath:/static/", "classpath:/public/")

This means, for spring it will first search in the resources folder of the classpath, and the in static folder, and lastly in the public folder (standard locations for resources).
But what we want is to add is the option to have a resource folder out of our jar and also to add the location of the webjar within our application without the client having to specific the full path.
classpathResourceLocations = (externalWebsite :: classpathResourceLocations) :+ s"classpath:/META-INF/resources/webjars/my.web-jar/$infoBuildVersion/"

The order that spring boot searches for resources is by the order of the string array for the locations. So the first entry will be a location to an external folder that can be specified in the application.properties in the format of a url (file:\...).
The second entry will be my web-jar with the fullpath of the resources inside the webjar. By doing this the client does not need to send the path, since we have added all the internal resources without the prefix.

Client Side Paths

 The last issue I wish to address is client side paths. The client side is written in angular so navigation in the java script is done by urls. So the client can have a url of : www.server.com\domain\method.
The “method” is not a endpoint in the server side but an endpoint in the client side. All this works fine until the user clicks on the page refresh. What then happens is that the URL is sent to the server, where the serve does not have the endpoint and returns a page not found error.
To fix this error we need to add View Controllers path in our WebMvcConfigurerAdapter as follows:
override def addViewControllers(registry: ViewControllerRegistry): Unit = {

  registry.addViewController("/").setViewName("forward:/index.html")

  registry.addViewController("/administration").setViewName("forward:/index.html")

  registry.addViewController("/license").setViewName("forward:/index.html")

  registry.addViewController("/404").setViewName("forward:/index.html")

  registry.addViewController("/download").setViewName("forward:/index.html")

}

In this method we will add all client side URL’s with a forward to the main page of the client indext.html. This will allow the server to accept the client endpoint and the redirect it back to the client.

Error endpoint

This all works fine unless the client endpoint is /error. Since this is a standard endpoint spring automatically implements this endpoint for us. Since we do not want this we must override spring’s default implementation as follows. In you configuration bean you need to add:
@Bean(name = Array("error"))

def defaultErrorView() : View  = {

  new RedirectView("index.html")

}

This implements the error bean of spring and tells spring to not use the spring implementation but in our case to redirect the error endpoint back to the client.



Saturday, January 16, 2016

Zip Streaming Log Files

Zip Streaming


The Scenario

I have a web server that supports debugging of my application. As part of the debugging I would like the option to download all log files that I have on my disk as a zip file.

Strait forward Solution

At first this looks like a very simple solution. I need to go over all the folders where I might have log files and add them to a zip file and then download the file.

Zip files

Java/Scala does not have a very convenient API for adding files to a zip file, but after searching the web it can be found (the issue is keeping the folder structure relative to a parent folder):
def createZip(folderParents: Map[File, List[File]]): ByteArrayOutputStream = {
  val bos = new ByteArrayOutputStream()
  val zipFile = new ZipOutputStream(bos)
  try {
    folderParents.foreach({ case (parentRoot, files) => createZip(zipFile, parentRoot, files) })
  }
  finally {
    zipFile.finish()
    zipFile.close()
    bos.close()
  }
  bos
}



def createZip(zipFile: ZipOutputStream, parentRoot: File, files: List[File]): Unit = {
  files.foreach(fileName => {
    val relativePath = parentRoot.toURI().relativize(fileName.toURI()).getPath()
    val zipEntry = new ZipEntry(relativePath)
    try {
      zipFile.putNextEntry(zipEntry)
      val buff = scala.io.Source.fromFile(fileName)
      val data = buff.foreach(zipFile.write(_))
      buff.close()
    }
    finally { zipFile.closeEntry() }
  }
  )
}

To then download the file from a spring boot server:
@RequestMapping(value = Array("/troubleshoot/logs"), method = Array(GET))@ResponseBodydef getLogFiles: ResponseEntity[Array[Byte]] = {
  val res = ZipUtils.createZip(folderParents)
  val headers = new HttpHeaders()
  headers.setContentType(MediaType.APPLICATION_OCTET_STREAM)
  headers.add("Content-Disposition","attachment; filename=\"log.zip\"")

  return ResponseEntity
    .ok()
    .headers(headers)
    .contentLength(res.size())
    .contentType(MediaType.parseMediaType("application/octet-stream"))
    .body(res.toByteArray);
}

Problem

The issues begin once we have very large log files. Once the log files are big (50mb and above) we start to see two issues. The first issue is that once the REST request is sent it can take a while until the file starts to download. The second issue is that we start to get out of memory exceptions.
The problem lies in the fact that to create the zip file I loaded all the files to memory and added them to the ZipOutputStream which is an in memory zip file. So what happens is that I need to load all the log files (maybe 500mb) and create the zip. Once the zip is created the download will begin. This also explains why I have an out of memory exception.


Solution

The ultimate solution to this problem is to stream the files to the client as we load them. This way we will solve both issues. We should not be loading all the files into memory.
To do this we need on one side to read the log files using a buffer and not load the full file (org.apache.commons.compress.utils.IOUtils is a good utility), and on the other side to stream the loaded data in a zip file - to do this we need to use GZIPOutputStream.
GZIPOutputStream allows streaming data to a zip file. The flow is: we load the log files, read into a buffer data, send the data to the zip stream, and the stream starts to download to the user. Then we continue this process, and we a have an end to end streaming will memory consumption of the buffer and no more.
The problem with GZIPOutputStream is that it does not support a folder structure. To solve this issue we will use the apache class TarArchiveOutputStream. The Tar Archive supports both folder structure and streaming. So we wrap the TarArchiveOutputStream with the GZIPOutputStream and then we get a folder structure that is both zipped and streamed down to the client.


def createTar(stream : OutputStream, folderParents: Map[File, List[File]]): Unit = {
  val tar = new TarArchiveOutputStream(stream)
  folderParents.foreach({ case (parentRoot, files) => createTar(tar, parentRoot, files) })
  tar.close()
}



def createTar(tOut: TarArchiveOutputStream, parentRoot: File, files: List[File]): Unit = {
  files.foreach(file => {
    val relativePath = parentRoot.toURI().relativize(file.toURI()).getPath()
    val tarEntry = new TarArchiveEntry(file)
    try {
      tarEntry.setSize(file.length())
      tOut.putArchiveEntry(tarEntry)
      IOUtils.copy(new FileInputStream(file), tOut);
    }
    finally {  tOut.closeArchiveEntry();   }
  })
}

val gzos = new GZIPOutputStream(outputStream)val buff = createTar(gzos,folderParents)
outputStream.flush()
outputStream.close()
 



Monday, November 9, 2015

Spring Boot Curator and ELK

Spring Boot Curator and ELK - JSON Message Log

Application Server

One of the things I love about spring is the simplicity of things. To create an application server that has a health and metric rest interface is very simple. For the application server I use Spring Boot (http://projects.spring.io/spring-boot/). For adding the health and metrics I use the Spring Curator (https://github.com/spring-projects/spring-boot/tree/master/spring-boot-actuator).
Now that I have my application up and running, I wan’t to monitor the application with a nice GUI with history. To do this I use ELK – Elastic Search, LogStash and Kibana. Kibana is the GUI interface. Elastic Search is the Database, and LogStash enters the data.
To implement this I could have added a mechanism to send my health and metrics directly to Elastic Search but this would be a solution specific implementation. I also do not want errors or checking of the Elastic Search Status in my application to run. This is where LogStash comes in. All I need to implement in my application is writing of the log files. Spring Boot comes with slf4j built in (http://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html). Now all that I need is to send my health and metrics to different log files for the LogStash to use.

Log Files

First step to create the log files is to use logback as our log implementation. For that you need to add to your resources folder the logback.xml file (http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-logback-extensions). Here you can define the rolling of the log file and the format.
To get the log files into Elastic Search you have two options. The first way is to configure the logstash to use parse the log files of spring boot using grok (https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html).
Since we know that we will be using LogStash it is better to have the log files formatted from the begging in json format for LogStash. To do this we will use the LogStash encoder for logback. For example:
<appender name="LogStashHealthFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <
encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
        <
providers>
            <
timestamp/>
            <
version/>
            <
threadName/>
            <
loggerName/>
            <
logLevel/>
            <
logLevelValue/>
            <
context/>
            <
arguments/>
            <
message/>
        </
providers>
    </
encoder>
    <
File>../log/log-stash-health.log</File>
    <
rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
       
<!-- rollover daily -->
       
<fileNamePattern>../log/archive/log-stash-health.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
        <
maxHistory>14</maxHistory>
        <
timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
           
<!-- or whenever the file size reaches 5MB -->
           
<maxFileSize>5MB</maxFileSize>
        </
timeBasedFileNamingAndTriggeringPolicy>
    </
rollingPolicy>
</
appender>

To use the encoder you need to add the following maven dependency:
<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>4.5.1</version>
</dependency>

This will create our log file as a json format for LogStash.

The Message Issue

The issue that I had a hard time with, and is the main reason for this blog is the json format of the message. The logback encoder creates a json out of the log entry, where the message is a field in the json. This field is recorded as a text field in the json object and not as part of the full json object.

For example:
{
            "@timestamp": "2015-11-09T10:11:19.026+02:00",
            "@version": 1,
            "logger_name": "com.clearforest.importer.log.health",
            "level": "INFO",
            "message": "{\"status\":\"UP\",\"queue\":{\"status\":\"UP\",\"Queue Name\":\"cmwell.files.ucpa\",\"Data Directory\":\"..\\\\data\\\\ActiveMQ\"},\"CMWell\":{\"status\":\"UP\",\"host\":\"vgilad:9000\"},\"nrg\":{\"status\":\"UP\",\"lastDataReceived\":\"09.11.2015 10:11:18\",\"lastWriteDate\":\"unknown\",\"cachedMessages\":1},\"diskSpace\":{\"status\":\"UP\",\"free\":24298827776,\"threshold\":10485760}}"
}

For Kibana to work we need the message of the log to be part of the full json object. To fix this when using the log in our code we need to add the following import:

import net.logstash.logback.argument.StructuredArguments._

This adds the option to pass arguments to the log file interface. The arguments are then added as a json object and not as a string field. In the code you then use the log as follows:

val res = RequestFactory.getRestContent(s"http://localhost:$serverPort/metrics")
meticLogger.info("",raw("metric",res))

and in the log file we will get

{
            "@timestamp": "2015-11-09T08:59:57.480+02:00",
            "@version": 1,
            "level": "INFO",
            "level_value": 20000,
            "health": {
                        "status": "DOWN",
                        "queue": {
                                    "status": "UP",
                                    "Queue Name": "files.abc",
                                    "Data Directory": "..\\data\\ActiveMQ"
                        },
                        "MyApp": {
                                    "status": "DOWN",
                                    "error": "Connection refused: connect",
                                    "host": "abc:9000"
                        },
                        "diskSpace": {
                                    "status": "UP",
                                    "free": 24000569344,
                                    "threshold": 10485760
                        }
            }
}



Friday, September 18, 2015

Spring Scopes – Decoupling code

Spring Scopes – Decoupling code


The Scenario

I have an application that has a lot of classes – more than 10. To simplify the issue, let’s say that I have a system that represents a school. So I will have a school class, a room class, teacher and all the rest, for example:
class School(){
  val classes : List[Class]
  def gotMoney(total: int)
}
class Class(){
  val teachers: List[Teacher]
  def updateTeacher(raise: int)
}
class Teacher(){
  def updateTeacherSalary(raise: int)
}

So we have in place - a school that has a list of classes that each has a list of teachers. The normal flow is that the school gets money and wants to give it to each teacher. So we have a method to pass the information from the School to the Class and then to each teacher.
Let’s say that I have a web application that calls the system, and we want to add a profile parameter that is sent during run time so that we can filter which teacher’s get a raise and which don’t.
How do we pass this new parameter from the Web API to the teacher class?

The Solution


Strait forward

A classic scenario is to add a new parameter “profile” to all the methods that need the profile. The limitation of this way is that we might want to add more than one parameter. In addition this is a legacy application that has a lot of spaghetti, so this would mean adding the parameter to a lot of methods that don’t really need to know about this.
What we really need is a way for a bunch of parameters to be entered in the Web API level and then be available to other places of code.

Scope Solution

Assumptions

The current assumption is that we have spring in place and that most of the service classes are spring beans.
So the actual solution is to create a session bean with scope prototype so that   we have a new bean each time that we need it. The bean is created on the Web API level and populated with the values, then in the lower level API the services that needs the new parameters will request the same prototype bean and get the values.
By using the prototype bean we also insure that are application can support multithreading and keep multiple instances of each session.

Standard web solution

If each bean will inject a standard prototype bean then each inject will get a new bean and the values will not persist. What we want is create only one bean per http request. For this spring invented a bean with scope of HttpRequest (http://www.tutorialspoint.com/spring/spring_bean_scopes.html). So what happens is that each time you request this bean spring will check if for this specific http request a bean has already been created. If yes you get the reference and if no you will get a new one.
For this to work your application must be a web-aware Spring Application Context. This is so that spring will hook into the http requests and know when to create a new instance.
But what if you want to use this same mechanism but you don’t have a web-aware context? If you did not have spring, the obvious solution would be to store the data you need on the local thread and then you can have access to it from any other class.
So spring actually supports another type of scope that is not in the standard documentation – thread.

Thread Scope

To definite your bean, you will use the standard definition of:
<bean id="sessionData" class="com.company.SessionData" scope="thread"/>

Spring has a class that implements the thread scope which is: SimpleThreadScope. It is a simple implementation with the limitation that it does not support a callback for the destruction of the bean, since it does not know when the thread is finished.
Since this is an unreleased class it is not supported by default and to use it you must register it with spring like any other custom spring bean:

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">

    <property name="scopes">

        <map>

            <entry key="thread">

                <bean class="org.springframework.context.support.SimpleThreadScope"/>

            </entry>

        </map>

    </property>

</bean>

.

Summary


When you need to change a lot of code due to API changes, you need to think out of the box and find a solution to magically pass the parameters from one section of the code to another. The solution to this is to isolate the parameters in a spring bean using the proper scope of the bean. You need to read up on spring scopes to find the specific scope that you need. Of course you always have the option to implement your own scope

Tuesday, May 12, 2015

Securing Tomcat

Securing Tomcat


Tomcat is a great web server. Though for production there is room for improvement.
There are some basic things that need to be done to make your tomcat secure. Some of them are simple like changing the default shutdown port to a different one. Others are simple but can be easily overlooked, like removing the default demo application and removing the management interface. For a list see: http://www.tomcatexpert.com/blog/2011/11/02/best-practices-securing-apache-tomcat-7.

Tomcat Users

If you want to use the tomcat manager application but what to use users, tomcat supports defining roles and users in the tomcat-users.xml file (see https://tomcat.apache.org/tomcat-7.0-doc/manager-howto.html). An example of this file is:
<tomcat-users>
                <user password="test" roles="manager-gui,manager-status,manager-script,manager-jmx" username="tomcat"/>
                <role rolename="admin"/>
</tomcat-users>
For the most part this is good enough, but what if you do not want your password in clear text? Tomcat supports the option to use MD5 instead of the clear text. To do this in the server.xml file, in the Realm node, you need to add the following:
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" digest="md5" resourceName="UserDatabase"/>

JMX Login

Most applications need a JMX MBean for debugging and monitoring. The JVM supports user name and password in the following way.
To your application you add the following JVM args:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8007
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.password.file={file_location}\jmxremote.password
-Dcom.sun.management.jmxremote.access.file={file_location}\jmxremote.access
You will need to change the ACL of the file for the jmxremote.password else the solution will not work (http://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html).

The problem is that the file with the password is still open and not encrypted. To fix this we need to implement our own Login Module using JASS (have a look at https://blogs.oracle.com/lmalventosa/entry/jmx_authentication_authorization).
The implement our own login module we need to change the JVM args to:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8007
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.ext.dirs={dir_location}
-Dcom.sun.management.jmxremote.login.config=AMFConfig
-Djava.security.auth.login.config={file_location}\AMF.config
-Dcom.sun.management.jmxremote.access.file={file_location}\jmxremote.access

For the login to work, the user still needs to be in the jmxremote.access file with the proper access level (readonly, readwrite).
We have added two new entries:
java.security.auth.login.config – this entirety will tell the JVM to load the JASS configuration file, for example:
TestConfig {
   plugin.com.tomcat.login.MyLoginModule Requisite passwordFile="\user\abc\jmxremote.access";
};
This will tell the JVM to use the class LoginModule for the JASS login. Since the configuration file can have more than one definition, you need to specific which module to use with: com.sun.management.jmxremote.login.config.
What they don’t write is that you need to create a separate jar that includes your login module (plugin.com.tomcat.login.LoginModule). Once you have this jar you need to put it in the java external folder. Adding it to the classpath is not enough. No we usually don’t have access to the java external folder, so since java 6 you can add another path for the external dir: java.ext.dirs. This will load all default external jars and your login.
An example code for the login module is:
public class MyLoginModule implements LoginModule {

       private Subject subject;
       private CallbackHandler callbackHandler;
       private Map<String, ?> options;
       private JMXPrincipal user;

       private boolean succeeded = false;

       public MyLoginModule() {
       }


       @Override
       public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
              this.subject = subject;
              this.callbackHandler = callbackHandler;
              this.options = options;
              succeeded = false;
       }

       //function for map
       private Map<String,String> getUserPassword(String passwordFile){
              Map<String,String> map = new HashMap<String, String>();
              File file = new File(passwordFile);
              if (file.exists()) {
                     try (BufferedReader buffer = new BufferedReader(new InputStreamReader(new FileInputStream(file)))) {
                           while (true) {
                                  String line = buffer.readLine();
                                  if (line == null)
                                         break;
                                  String[] fields = line.split("\\s+");
                                  String fileUser = fields[0];
                                  String filePassword = fields[1];
                                  map.put(fileUser, filePassword);
                           }
                     } catch (IOException e) {
                           return map;
                     }
              }
              else{
                     System.out.println("password file not found: " + passwordFile);
              }
              return map;
       }
      
       public boolean validateUser(String passwordFile, String userName, String password) {
              String md5 = EncryptionHelper.md5(password);
              Map<String, String> userPasswords = getUserPassword(passwordFile);
              String filePassword = userPasswords.get(userName);
              if (md5.equals(filePassword)) {
                     return true;
              }
              return false;
       }

       @Override
       public boolean login() throws LoginException {
              String passwordFile = (String) options.get("passwordFile");

              if (callbackHandler == null) {
                     throw new LoginException("Oops, callbackHandler is null");
              }

              Callback[] callbacks = new Callback[2];
              callbacks[0] = new NameCallback("name:");
              callbacks[1] = new PasswordCallback("password:", false);

              try {
                     callbackHandler.handle(callbacks);
              } catch (IOException e) {
                     throw new LoginException("Oops, IOException calling handle on callbackHandler");
              } catch (UnsupportedCallbackException e) {
                     throw new LoginException("Oops, UnsupportedCallbackException calling handle on callbackHandler");
              }

              NameCallback nameCallback = (NameCallback) callbacks[0];
              PasswordCallback passwordCallback = (PasswordCallback) callbacks[1];

              String name = nameCallback.getName();
              String password = new String(passwordCallback.getPassword());
              user = new JMXPrincipal(name);

              if (validateUser(passwordFile, name, password)) {
                     succeeded = true;
                     return succeeded;
              } else {
                     succeeded = false;
                     throw new FailedLoginException("Wrong Login! Incorrect User or Password");
              }
       }

       @Override
       public boolean commit() throws LoginException {
              subject.getPrincipals().add(user);

              return succeeded;
       }

       @Override
       public boolean logout() throws LoginException {
              subject.getPrincipals().remove(user);
              return false;
       }

       @Override
       public boolean abort() throws LoginException {
              return false;
       }
      
}

Debugging

To debug the login you have a few options. The regular attach process will work nicely and you can debug your login. In addition on the server side you can add the following system parameter: -Djava.security.debug=all.
Also on the client side you can run the jconsole from the command line with the following parameter:
Jconsole –debug. This will open a debug window and print the errors from the server side.