Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Monday, October 08, 2018

Enable gc log

When your Java app is running very slow there's a chance that it is caused by some pauses in your app which in turn caused by the diligent garbage collector who loves to take its time cleaning up the memory for you way too often and too long :)

These two steps you might want to do to make sure that it was GC doing its job:
1. Extract the GC log from your app
2. Analyze the log

Extracting GC Log

For extracting the gc log, here's my preferred settings:

-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCApplicationConcurrentTime
-XX:+PrintGCDateStamps
-Xloggc:gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=2000k


Add those parameters above on your java runtime parameters, for tomcat you could edit catalina.sh (or catalina.bat), find JAVA_OPTS and add them there.

Restart your Java app or app server and find gc.log on the current directory where you run your java app.

Analyzing GC Log

Refer to the reference 1 below on how to learn to interpret the gc log.
For the tools, choices are you do it using offline tool or online tool.
1. Offline
I'm using GC Viewer (see reference 3 below), simple and easy tool

2. Online
Try gceasy.io, it analyzes your gc log quite awesome :)


Reference:

1. https://dzone.com/articles/enabling-and-analysing-the-garbage-collection-log
2. http://gceasy.io
3. https://github.com/chewiebug/GCViewer

Thursday, September 03, 2015

Tomcat JMX Monitoring

Monitoring Tomcat's resources could be done using the JConsole app which already included in the JDK. In order to monitor Tomcat, we also need to prepare the Tomcat first.



To configure Tomcat in *nix environment, you need to add the parameter below when starting tomcat:
-Dcom.sun.management.jmxremote
  -Dcom.sun.management.jmxremote.port=%my.jmx.port%
  -Dcom.sun.management.jmxremote.ssl=false
  -Dcom.sun.management.jmxremote.authenticate=false

To add the configuration above, one of the way is as below:
1. Open your catalina.sh
2. Add below line (example port is 12300)


3. Restart your tomcat
4. If you need to access it from other computers, make sure the firewall configuration  allows the configured port to be accessed from outside
5. In case the remote connection is not working, try to add below line in the configuration
    -Dcom.sun.management.jmxremote.host=localhost


Reference:
- https://tomcat.apache.org/tomcat-7.0-doc/monitoring.html
- http://docs.oracle.com/javase/6/docs/technotes/guides/management/jconsole.html

Tuesday, August 14, 2012

Struts2 in Websphere 6.1

Just when someone asked you if Java really delivers what it promises, especially about compile once run anywhere. I just deployed a webapp developed using Struts 2, Spring, Hibernate in Websphere 6.1. And as expected, the deployment failed. After a few googling around and friend's advice, it turns out that I have to configure some properties for the server.

Here are the properties:


















The new properties added are the last two, and here is a bit explanation on the property:
- com.ibm.ws.webcontainer.invokefilterscompatibility = true
 Quoted from ibm docs (see here)
With this custom property, the Web container calls custom servlet filters before looking for welcome files. Also, if the Web container cannot find a resource, it calls the custom servlet filters before creating a FileNotFoundException exception. This change enables the Web container to verify whether the custom servlet filters modify the path to a resource. 
In short, this property enables custom servlet filter to process http request and Struts 2 utilizes Servlet Filter.

- com.ibm.ws.webcontainer.assumefiltersuccessonsecurityerror = true
Quoted from ibm docs (see here)
When a request is received for a static file which does not exist, the web container calls defined servlet filters. If the filters do no successfully complete, a 404 error code is set. In a situation where application security is enabled, a security check is performed as part of filter invocation. Typically if the security check fails the web container considers the filters to have failed and still sets a 404 error code instead of the 401 error code that indicates the failure of a security check. The 404 error code enables the requester to access the static file without logging on.
 In short, just to be more secure this property is set to true. Anyway, this property doesn't have any thing to do with Struts 2.


To make sure everything works, don't forget to restart the server.



Wednesday, September 07, 2011

Tracking Hibernate SQL query and parameters

Every developer using Hibernate might need to know the SQL it generates and the parameters being sent. Normally to have the sql printed out to console, one only have to configure hibernate property show_sql to true. However the parameters are not printed out.

Luckily for me, I found this post on configuring the necessary log level to be able to print out the sql and parameters. Here are the configuration that I used:

org.hibernate.SQL=DEBUG
org.hibernate.type=TRACE 


Saturday, March 19, 2011

How to configure the way BeanUtils converts null value

By default BeanUtils.setProperty always assign a default value for null. For an instance, if the property's type being set is Integer then you will get 0. This could be the behavior that many do not expect, for example you use Struts and you have an entry form with a number field. And you're expecting that if the user leave it empty, you would like to display it as empty later on.
BeanUtils utilized by Struts will fill the field as 0 instead of leaving it null.

Underneath BeanUtils is utilizing a ConverterUtils to convert the value before setting it to the property. Therefore to change this behavior all we need to do is to register a new IntegerConverter to ConverterUtils, thereby overriding the default converter used.

e.g.
ConvertUtils.register(new IntegerConverter(null), Integer.class);

The same thing you should do for other types as needed.

If you indeed configure the converter, you might want to read this.

Tuesday, March 15, 2011

Understanding seam's persistence context configuration

Actually this post is a note for myself regarding how seam could be configured in the web application. The facts are:
- The application is running on JBoss 5.1
- Seam is used to manage the lifecycle of EntityManager instances

Here's the configuration:
  1. Datasource configuration file placed in {server}/deploy
    JNDI name is Datasource
  2. Persistence unit configuration in persistence.xml
    <persistence-unit name="PersistenceUnit" transaction-type="JTA">
    <provider
    >org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>Datasource</jta-data-source>
    ......
    <properties
    >
    ........
    <property name="jboss.entity.manager.factory.jndi.name" value="java:/EntityManagerFactory"/>
    </properties>


  3. Declaration of persistence-unit-ref element in web.xml
    <persistence-unit-ref>
    <persistence-unit-ref-name>PersistenceUnit/pu</persistence-unit-ref-name>
    <persistence-unit-name>PersistenceUnit</persistence-unit-name>
    </persistence-unit-ref>

  4. Configuration in component.properties
    seamBootstrapsPu=false
    seamEmfRef=#{null}
    puJndiName=java:comp/env/PersistenceUnit/pu
  5. Configuration of persistence managed context in components.xml
    <persistence:managed-persistence-context name="entityManager" auto-create="true"
    entity-manager-factory="@seamEmfRef@"
    persistence-unit-jndi-name="@puJndiName@"/>


Here's the short explanation:
  1. A new datasource is deployed (step 1)
  2. The datasource is referred to in persistence.xml (step 2)
  3. Add reference to the new persistence unit name in web.xml (step 3)
  4. Add new property in component.properties which refers to the persistence-unit-ref-name declared in web.xml (step 4)
  5. The values configured in component.properties is used to configure the managed-persistence-context (step 5)

Note: The entity manager factory is bound to the global JNDI thru "jboss.entity.manager.factory.jndi.name" property configured during step 2, however it is not used... yet :)

Thursday, March 10, 2011

Beware of customizing BeanUtils converter

If you ever have to customize BeanUtils converter just like I did, one thing that should be of your concern and that is BeanUtils is also utilized by many open source libraries. And some of the libraries might happened to have the same need as yours to customize the converters. If in any case you are using one of those libraries, it just might override your converters.

In my case, I was using jXLS . It is a great tool and it's my fault that I didn't read the documentation thoroughly. The documentation says:

"jXLS integrates with Jakarta BeanUtils conversion utilities to perform actual conversion from Excel cell values into bean properties...... BeanUtils Converters for primitive types return a default value when a conversion error occurs. jXLS overrides this behaviour in ReaderConfig class registering these classes to throw a ConversionException."

And what I configured for my application is for BeanUtils to return null for empty string instead of the default value.

Now, here's a short story on what truly happened to my application due to the conflict described above:
At first, an empty text field (for number input) in the form is converted to null and after some operations performed on the application "suddenly" it throws NumberFormatException for empty text field in the form. I'm lucky to know the steps to reproduce it and it turns out that things started to act strange after jXLS is utilized (to create/read excel file).

At this point, I'm grateful to have jXLS and BeanUtils source code. I could just debug into the source code and analyze it. And I found out that jXLS overrides BeanUtils's converter configuration as the documentation said. Now all I can do is after every invocation of jXLS I have to reconfigure BeanUtils as my application need it.

One more thing still disturb me, how to handle concurrent processes where one process is still working on jXLS and the other one need to convert the value from the form. And both are utilizing BeanUtils. I guessed at this moment I have to accept that I will get NumberFormatException and tell the user to try to submit the form again (and hoping that the jXLS process is already finished).

Tuesday, September 14, 2010

Using hibernate generated collection in h:dataTable

It's a bit difficult to pick the correct title for the thing that I'm going to write :) It's about having your POJO generated by hibernate and then feed it to h:dataTable.

When your object has a collection properties and the elements contained are unique within the collection, hibernate will create a Set to contains it. The thing with a Set is h:dataTable just can't accept it. The simplest solution is to change Set to Collection object and h:dataTable can accept it and Hibernate won't complain about it :)

Rolling back transaction (Seam managed transaction)

JSF+Seam is what I'm learning at the moment. And the case is I need to rollback the transaction due to business exception but I don't want to not catch the transaction (when a runtime exception is uncaught the transaction will be rollback automatically). The business exception here is a new exception class extending RuntimeException.

At first try, I add ApplicationException annotation with rollback = true in my BusinessException class. The controller class which invokes the business service class and under certain condition an exception of BusinessException type is thrown. In my scenario my transaction should be rolled back, the thing is... it was not rolled back.

This forced me to dive into seam's code (that's why I love open source) and find out how to handle the transaction. And I came into Transaction class, which I can use to do what I want.
Here's how to use it to mark the transaction as rollback:

Transaction.instance().rollback();

Actually all I wish is when the exception is thrown by the service class (already registered to seam) the transaction will be rolled back automatically, unfortunately for me it doesn't work :(

Entity inheritance-single table per class hierarchy strategy with JPA + Hibernate

I happened to have the chance to implement entity inheritance using single table per class hierarchy strategy. At first I though I would sail smooth and arrive at the promised land easily :) but as usual with programming, it is a rare thing a code would sail smooth at the first time.
Persisting entity works like charm, retrieving it makes me speechless. Here's an example:

The base class (ItemReference)


Subclass#1 (ItemReferenceAge)


Subclass#2 (ItemReferenceSex)


DDL


One class that I don't include here is the class which has a collection of ItemReferenceSex and a collection of ItemReferenceAge, let's call this class Wrapper.

The scenario is I add 2 instances of ItemReferenceAge to wrapper collection and persisted it. What happened when I try to load the same wrapper instance is both collections are having elements in them. Remember, I only add ItemReferenceAge instance which means the collection of ItemReferenceSex should be empty.
Looking at the query generated shows that the discriminator column is not used in the where clause of the select query. What I can think of the design reasoning is that it is assumed that there will not be two or more type of instances loaded in the same parent object which in my case it is.
Luckily for me, there's a solution for this and unfortunately it's hibernate specific annotation (is it maybe because of JPA doesn't state how to handle my case or is it hibernate implementation?). All I need to do is to add ForceDiscriminator annotation in my base class and the problem is solved!

Thursday, August 19, 2010

Eclipse fails to start?

Your eclipse fails to start? actually we could say your workspace fails to start. I've gone through it several times and my solution was to create a new workspace and import the existing projects into the new workspace.
However, this time I'm trying to solve it once for all (as though it's possible :). Googled around and I found, imho, a rough solution that works for me. It's as simple as deleting org.eclipse.core.resources folder inside {workspace}/.metadata/.plugins and then run eclipse -clean.
The result is eclipse is working but I still have to import the existing projects back. The good thing is I don't lost all the preferences and server setting (though I could just import the preferences file I once exported).

Check the link on the title and also this one, tools from eclipse team that maybe could help with the broken workspace (I never tried it yet... my workspace already fixed :)

Tuesday, August 17, 2010

A bit on classloader

At first glance, I thought java could face the same problem as dll was (dll hell). But then classloader scoping comes to the rescue. And by the way, I won't explain the theory of classloading here. By having classloader scope set to the application, it will allow each application to bring their own libraries without worrying of library conflict.

For example, I built a library of common utilities and there are already 2 versions of it. And 2 of my web applications are using the library, however each with a different versions from the other. If the flat classloading is used, only one of the 2 versions of the library will be used and the impact is the web application which used the version not loaded will have strange errors such as ClassCastException, IllegalAccessErrors and possibly many others. Having classloader scoping will allow each of my web application to use its respective library.

One thing cross my mind, how could I have a smaller deployment size for a web application and still having the classloader scoping. Smaller deployment size here refers to my classes only without the whole bunch of libraries. Usually when people delivers a patch for the web application, all is packed in war file which size is quite large. On my case, the library size are around 80% of the war file size. Up to now, all I can do is to deploy the application as exploded. Thus allowing me to deploy patches by replacing the content/libraries. Not an elegant solution but still a viable one, until I can find a nicer solution.....

Sunday, August 15, 2010

Initialize static List and Map

If you intend to create a List or Map for your constants, here's how you do it.

List

public static String CONSTANT_1 = "1";
public static String CONSTANT_2 = "2";

public static List CONSTANTS = new ArrayList() { {
add(CONSTANT_1);
add(CONSTANT_2);
}};


Map


public static Map CONSTANTS = new HashMap() { {
put("key1", "value1");
put("key2", "value2");
}};


Even better is to wrap the ArrayList/HashMap by passing them to Collections.unmodifiableList or Collections.unmodifiableMap. Thus making sure that it is truly a constant list/map.

Saturday, July 24, 2010

Retrieving generic's Class type

Quite few times I've been using generic and I needed the Class type. I found out that I've to pass the class type instead of extracting the class type from the type parameter. This story comes to an end when I found out a way to extract the type, thanks to Type interface :)

Here's the recipe:
- First extract the genericSuperclass
- Retrieve the actual type arguments

.. and the code is:
ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
Class classType = (Class) type.getActualTypeArguments()[0];

ParameterizedType represents an invocation of a generic class or interface, better explanation could be read in the javadoc.

That's all... :)

Friday, June 05, 2009

MD5 hash

This morning I read a blog discussing about how to keep a secure password. The usual way to store a password is first to hash it using MD5 hash and store it in a db. The benefit of using MD5 is you cannot do a reverse-hash.

Here's how you code it in Java :

MessageDigest md = java.security.MessageDigest.getInstance("MD5");
md.update("your password here");
byte[] hashed= md.digest();


To convert it in hex, here's the code (actually I got it from here):



One more tips, for better security, you might consider to add salt before hashing the password to make it less vulnerable. The changes looks like this :

md.update("The salt" + "your password here");

"The salt" here should be created dynamically and stored it along with the hashed password to be used later.


An excellent post on secure password scheme could be found here.

Saturday, October 11, 2008

Debugging application server as remote application

The need was to debug Resin 3.1.0 in eclipse, however there's no plugin for Resin 3.1.0 in eclipse (at least until now) to my own amazement.
Fortunately, there's still a workaround which is to debug the application server as if it is a remote java application.

To do that, we need to add the parameter below before starting the server

-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=12345

(-Xnoagent already deprecated, we could remove it anyway, so why do I put it there? Just to let you know that it exists and if you still use JDK1.1 then use it otherwise loose it)

Adding the parameter above means that we could attach a debugger to localhost:12345 (assuming I'm debugging application server running at my computer), the address could be adjusted to a different port as long as the port is unused.

Then on the IDE of your choice (I've tried eclipse and netbeans), just open a remote debug session and put localhost as the host and 12345 as the port. If your IDE successfully attaching a debugger to the server, then all you need to do is set breakpoint(s) to your application code which was deployed to the server. Access the application and the server will be suspended when it arrives at the breakpoint set before.

That's all for now, any question just shoot.

Note : I'm not explaining all those parameters in detail, if you're interested, please visit this link.

Wednesday, October 08, 2008

Calling webscript with no Basic authentication

My case was that I need to invoke web script without triggering the HTTP basic authenticator, 1 week of reading the wiki and googling, I almost accept that web script requires HTTP basic authentication.
But thanks to the answer on my alfresco post, there are 3 ways of authentication for web script.

  1. /alfresco/service or /alfresco/s (mapped to HTTP Basic Authenticator)
  2. /alfresco/wcservice or /alfresco/wcs (mapped to Web Client Authenticator)
  3. /alfresco/168service or /alfresco/168s (mapped to JSR-68 Authenticator)

I could use /alfresco/wcs to invoke my web script from my dashlet without popping up the authentication dialog box and it opens up the possibilities for me integrating other applications :)

Saturday, October 04, 2008

Starting an alfresco workflow using Javascript API

The script to execute workflow is as below :

var workflow = actions.create("start-workflow");
workflow.parameters.workflowName = "jbpm$sanz:testWorkflow";
workflow.parameters["bpm:workflowDescription"] = upload.name;
workflow.parameters["bpm:groupAssignee"] = people.getGroup("GROUP_IT Manager");
workflow.parameters["sanz:notifyMe"] = true;
var futureDate = new Date();
futureDate.setDate(futureDate.getDate() + 7);
workflow.parameters["bpm:workflowDueDate"] = futureDate;
workflow.execute(document);


A bit explanation :
  • "start-workflow" is the action name to create a workflow action (see Action API)
  • workflow name is prefixed by "jbpm$", the workflow name used is the name set in the process definition along with its namespace
  • other parameters as defined in the task(inside the start-state) 's type could be set here, e.g. the "sanz:notifyMe" property in the example above
  • pass a document (Content noderef) to workflow.execute. Remember if we start a workflow from the web-client interface, we always start from a content/document

Tips :
  • if you want to pass a group as the groupAssignee, we can use people.getGroup(groupName) API, but one thing to note, the group name to pass is : GROUP_group name. You should add "GROUP_" prefix to your group name.
  • to pass assignee, use people.getPerson(assignee name)
  • to pass assigness, wrap the assigness as array, using [], e.g. [people.getPerson("me"), people.getPerson("you")]

I guess that's all for now. Next target, synchronize user/group to ldap (or from ldap?)

Custom workflow in alfresco

Alfresco, at first glance it looks like just another document management system.. wait, I'm not here to talk about alfresco as a DMS, let's get back to the main topic.

How to create a custom advance workflow in Alfresco

Before continuing, the main reason I'm writing this is to make life a lot simpler for developers who are told to create an advance workflow (I hope), where I'm having a hard time myself creating one.

One thing to note, I'm not repeating what is already in the manual, so better to read the manual first.
  1. Read http://wiki.alfresco.com/wiki/WorkflowAdministration first.
  2. Create the process definition, things to note :
    • Declare the swimlane for each actor/group of actors, one special swimlane called Initiator (which represent the initiator of the workflow)
    • Another special state is start-state, this is the point where we collect required parameters for the workflow to start, e.g. the reviewer, due date, etc (just remember this at this moment).
    • Declare task for each task-node
    • For each task declared, specify the swimlane (if we don't, who will handle the task?)
    • For each task declared, specify a name for the task. The task name relates to the type of model that we will use, either create a new one or use an existing, e.g. wf:submitAdhocTask
    • Deploy the new process definition, it's easier to deploy the process through JBoss jBPM Process Designer
    • Alternatively instead of using the process designer, you could put your definition file in [Alfresco installation]\tomcat\webapps\alfresco\WEB-INF\classes\alfresco\extension, create a "workflowDeployer" spring configuration and add the spring configuration to classes/alfresco/application-context.xml
  3. Create a new model or use an existing one. To create a new model :
    • You can safely follow what's in the manual (step 2 : Create the task model)
    • Declare your own namespace (for those who aren't familiar with xml terms, namespace is like a package in Java, you could specify your own URI)
    • Import bpm's type, by adding the import statement specifying the bpm uri.
    • Create type for each task in the process definition, to be exact, the name of the type is the same name as the task's name. Don't create the type if you use an existing one in your task
    • Each type should has a parent, remember that we're creating types for process not for other purpose, the parent should be a bpm type. For type for task in start-state, the parent is bpm:startTask, for the other, we could use bpm:workflowTask
    • To view/modify content on the workflow on a specific task, we have a workflow package operation ready for use, see the manual on http://wiki.alfresco.com/wiki/WorkflowAdministration#Workflow_Package_Actions
    • Since the new type extends bpm's type, some properties are already in place, to introduce new one just declare the properties inside the type, see the manual on http://wiki.alfresco.com/wiki/WorkflowAdministration#Step_2:_Create_the_Task_Model
    • Deploy the model
      • Put your model in [Alfresco installation]\tomcat\webapps\alfresco\WEB-INF\classes\alfresco\extension
      • Create a new spring configuration file to load the model. The file name should end with context.xml (e.g. my-file-context.xml), put it in extension directory, alfresco will pick it up when it starts, see the manual for sample spring beans definition on http://wiki.alfresco.com/wiki/WorkflowAdministration#Deploying_the_Task_Model
      • Restart the server

  4. Create web client configuration, the purpose is alfresco doesn't know how to render the "type" that we just created, it needs the so called web-client configurator. I have nothing to say about this, so just read on the available manual One thing to note, update web-client-application-context.xml to load the custom web-client-xxx-config.xml
  5. Prepare resource bundle for the workflow, my advice is to look at workflow-messages.properties located at ...\classes\alfresco\workflow. Look at the pattern and follow it for your process and types.
  6. Behavior can be added and I'm not going to discuss about it here. One note, it's a bit difficult for me to find a documentation on Alfresco Javascript API, if you're trying to find out what are the properties that a certain root object has, use Alfresco's javascript console and browse through the root object's properties
  7. Use workflow console!!! the url is /alfresco/faces/jsp/admin/workflow-console.jsp. It can undeploy definitions, just what you need when you're in a development stage and still a lot of features that you will surely need

In summary, list of files created :
  1. JPDL (process definition file)
  2. if we do manual deployment, we need custom spring context to deploy the jpdl (along with the model also if needed)
  3. model
  4. custom spring context file (to load the model)
  5. web client config file to tell alfresco how to render our model
  6. Message properties
That's all for now and I might add some other things later. Indeed, it's exciting to use Alfresco, still a lot to learn.

Another source that might help : http://ecmarchitect.com/archives/2007/06/09/756

Wednesday, October 01, 2008

java.awt.headless

We were using JFreeChart at that time, on our development machine everything ran smooth, chart appeared, no error. Until we deployed it on the production server (wait, am I not mentioning any staging server here? yep, no staging server mentioned.. just another recipe for disaster), the chart was gone, error message was the only clue we had. Google here, google there and we ended up with this great remedy that saved our asses.

The error message was :
Can't connect to X11 window server using ':0.0' as the value of the
DISPLAY variable.
java.lang.InternalError: Can't connect to X11 window server
using ':0.0' as the value of the DISPLAY variable.

I've tried to set the DISPLAY variable in the environment to no avail, the other solution we found was to set java.awt.headless=true, indeed this was the option that we need to add before we run the server.
The key was on the production server there was no X-server running (we used rhel), everything done thru the console (which bring to my mind, what is wrong with having a nice GUI helping you, instead of all in text... i'm not against it, I'm just looking for improvement).
Setting headless to true, tells the jvm that it lacks either display device, keyboard or mouse. Luckily for us JFreeChart doesn't use any graphical components that requires a display device.

One more thing to consider if someone is going to build a component related to displaying things on screen.