Due to some changes in the blogosphere, I moved the blog entries to:
http://braindrainpain.com
Update your links accordingly.
zaterdag 13 december 2014
donderdag 3 april 2014
Glassfish 4 Language Settings
If you want to override the language of the Glassfish 4 Server itself, you can add the following option to the JVM options of the domain:
You can add it to the domain.xml directly or you can open the admin console, go to the configuration pane, open the server-config, JVM-settings and then the JVM-option tab.
You can add it to the domain.xml directly or you can open the admin console, go to the configuration pane, open the server-config, JVM-settings and then the JVM-option tab.
woensdag 30 oktober 2013
Trailing slashes in Jersey REST WebResources
For the REST-purists under us, a resources ending with a slash is not the same as a resource ending without a slash. However, the difference between url://xxxx.com/a and url://xxxx.com/a/ is ignored. The trailing slash is omitted.
When you try to map a resource with a trailing slash using the standard @Path annotation, the methods get mapped to the same endpoint causing an exception.
Glassfish answers during the deployment with:
When you try to map a resource with a trailing slash using the standard @Path annotation, the methods get mapped to the same endpoint causing an exception.
Glassfish answers during the deployment with:
SEVERE: Following issues have been detected: WARNING: A resource model has ambiguous (sub-)resource method for HTTP method GET and input mime-types as defined by @Consumes and @Produces annotations at Java methods ... These two methods produces and consumes exactly the same mime-types and therefore their invocation as a resource methods will always fail.In Glassfish which uses the Jersey under the hood, the slash is also ignored. But there is a workaround. You can use regex in the Path-annotation to map resources ending with a slash. In the example at the end, I use regex to map the paths to the methods. But there is something you should know about the path-matching algorithm. The mapping algorithm uses the following rules:
The JAX-RS specification has defined strict sorting and precedence rules for matching URI expressions and is based on a most specific match wins algorithm. The JAX-RS provider gathers up the set of deployed URI expressions and sorts them based on the following logic:In the following example, test2 is found before test1 because the regex is longer! We check the trailing slash first. When it fails, it falls back to test1.
- The primary key of the sort is the number of literal characters in the full URI matching pattern. The sort is in descending order.
- The secondary key of the sort is the number of template expressions embedded within the pattern, i.e., {id} or {id : .+}. This sort is in descending order.
- The tertiary key of the sort is the number of nondefault template expressions. A default template expression is one that does not define a regular expression, i.e., {id}.
woensdag 28 augustus 2013
MySQL YEARWEEK() function in Java (ISO 8601)
It is not unusual to use MySQL's YEARWEEK() function to create identifiers for weeks within years. The problem is well-known. You need to store the week number for a certain year. Storing only the week-number decouples your data from the real year. You need to store the year too and that's when YEARWEEK kicks in. But beware, there are some pitfalls!
There is an agreement on the week-calculation. It defined as ISO 8601. The first weeks must have at least 4 days and starts on a monday. See http://en.wikipedia.org/wiki/ISO_8601 for more information.
Unfortunately, MySQL uses mode "0" for the week-calculation. It is not the ISO 8601 norm. You must set MySQL to use mode "3" (default_week_format) or pass it as a parameter in the YEARWEEK() function.
So, the following problems are solved:
gives us 201253.
gives us 201301 which adheres to the ISO 8601.
Ok, this problem seems solved. The database seems to have the dates correct. But if I want to query the week, I cannot always rely on the database to calculate me the correct date. Sure, I could do round-trips to the server sending a date and receiving the correct week number. But that's slow.
The package Joda helps us out and provides the solution. Out of legacy-grounds, the API works with a calendar object. Joda provides us the correct week in the year and the correct year for the that week (even though the real year is different).
I wrote a test-class with the Java-method to generate the values.
I've tested the results agains the MySQL YEARWEEK for 12 years and all seems to work fine!
MySQL
The YEARWEEK()-function gives us something like 201304 for the fourth week of 2013. But that's only half the story. Problems arise when you want to know the week-number for 31.12.2012. This could be 201253 or 201301, depending on how you see it. The week could start on monday, or sunday and the first week of the year starts after 4 days or not.There is an agreement on the week-calculation. It defined as ISO 8601. The first weeks must have at least 4 days and starts on a monday. See http://en.wikipedia.org/wiki/ISO_8601 for more information.
Unfortunately, MySQL uses mode "0" for the week-calculation. It is not the ISO 8601 norm. You must set MySQL to use mode "3" (default_week_format) or pass it as a parameter in the YEARWEEK() function.
Mode | First day of week | Range | Week 1 is the first week … |
---|---|---|---|
0 | Sunday | 0-53 | with a Sunday in this year |
1 | Monday | 0-53 | with more than 3 days this year |
2 | Sunday | 1-53 | with a Sunday in this year |
3 | Monday | 1-53 | with more than 3 days this year |
4 | Sunday | 0-53 | with more than 3 days this year |
5 | Monday | 0-53 | with a Monday in this year |
6 | Sunday | 1-53 | with more than 3 days this year |
7 | Monday | 1-53 | with a Monday in this year |
So, the following problems are solved:
gives us 201253.
gives us 201301 which adheres to the ISO 8601.
Ok, this problem seems solved. The database seems to have the dates correct. But if I want to query the week, I cannot always rely on the database to calculate me the correct date. Sure, I could do round-trips to the server sending a date and receiving the correct week number. But that's slow.
Java
Let's try to rebuild the YEARWEEK() in Java using the ISO 8601 norm. The Calendar-class is not the solution we're looking for. Sure, you can get the week, but you can't get the correct year for that week when you're in the ISO 8601 mode. For example, for 2012-12-31 you get the week 01 but the year 2012, resulting in 201201 for the last week of the year. Which is of course, incorrect!The package Joda helps us out and provides the solution. Out of legacy-grounds, the API works with a calendar object. Joda provides us the correct week in the year and the correct year for the that week (even though the real year is different).
I wrote a test-class with the Java-method to generate the values.
I've tested the results agains the MySQL YEARWEEK for 12 years and all seems to work fine!
dinsdag 30 juli 2013
The best DROP-script for Mysql!
There are many situations in which you want to drop all tables in a MySQL database. You can easily drop the schema, but then all the permissions are lost too. There are several solutions out there, but they all require some manual effort. I wanted to get rid off it once and for all and constructed this easy script. With the following evil shell script you can easily drop all tables in your database.
Premisse: it uses a group on table_catalog which may not always be the correct grouping in your database. Please, feel free to adapt!
Just create a textfile like drop.sh and give it appropriate rights to execute. The paste the following content in the file and save it.
Use ./drop.sh root root my_db et voilá.... all tables are gone.
Off course, things can be improved. I need to check the parameters and add some documentation...
Premisse: it uses a group on table_catalog which may not always be the correct grouping in your database. Please, feel free to adapt!
Just create a textfile like drop.sh and give it appropriate rights to execute. The paste the following content in the file and save it.
Use ./drop.sh root root my_db et voilá.... all tables are gone.
Off course, things can be improved. I need to check the parameters and add some documentation...
vrijdag 26 juli 2013
Tuning suspended AsyncResponse and Thread-pools in Glassfish 4
I am experimenting with Glassfish 4 to prepare in order to move some application from J2EE6 to J2EE7. Glassfish 4 works with J2EE 7 and introduces some new concepts. The one which we are investigating today is the use of @Asynchronous and @Suspended in REST resources.
The use of the asynchronous annotations is pretty well specified for beans but there are some pitfalls when it comes to REST services. Let's go through an example and check the behavior of a REST service with asynchronous methods as we go.
The use case is the following. We define a Resource and one Bean. The resource is a typical REST-resource with only one GET-method. The bean is a normal, stateless session bean which performs a long running task. This bean is pretty straightforward. We do not annotate the methods of the bean as asynchronous.
The first resource we build is pretty simple. We create an @Stateless resource and inject a @Suspended AsyncResponse. AsyncResponse takes care of the asynchronous response when the results become available.
When we open the browser and point to the URL of this resource we will see that the request is blocked for 10 seconds! But that is nothing new. Now, the problem is that we want to know how many threads are available to serve these requests. We are using a stateless bean, so we use the thread-pool of the ejb-container. This has some implications. When we use the http-thread-pool we will basically the same behavior, but we are not interested in the request thread. I want to scale out the ejb-pool. Adding beans to the pool is apparently not enough.
When you press F5 continuously in the browser, you will see something like "INFO: do a long task in thread: __ejb-thread-pool1" in the log. This number counts up and exceeds the threads in the http-thread-pool thanks to the AsyncResponse and @Suspended. But you will see (in a freshly installed domain) that the thread-pool does not exceed the limit of 16 even though you have max. 64 beans in your pool. We need to finetune the thread-pool of the ejb-container. But, you won't find any properties in the administrator console. You need to add them yourself. Open the domain.xml of your domain and add the following lines:
Now, rerun your application. You will see that the thread-pool goes up to 10 when you press F5 in the browser without holding it down. It seems to stagnate on 10 although you kinda specified a max-pool-size of 20. When you continuously press F5 you will suddenly see the threads go up to 20 before throwing an java.util.concurrent.RejectedExecutionException. Nice, but what the hell happened?
Let's dig deeper in the documentation of the thread pools:
thread-core-pool-size: Specifies the number of core threads in the EJB container’s common thread pool. The default value is 16. Great, there we have our number 16. Setting this to 10 oder 100 will change the actual number of threads doing some work.
thread-max-pool-size: Specifies the maximum number of threads in the EJB container’s common thread pool. The default value is 32. Nice, increasing this to 100 will be the maximum number of threads we can use? Yes and no. You have to consider the default-value of thread-queue-capacity.
thread-queue-capacity: Specifies the size of the thread pool queue, which stores new requests if more than thread-core-pool-size threads are running. The default value is the Integer.MAX_VALUE.
Here starts the confusion. Your queue-capacity is way too high. Pressing F5 will never reach MAX_VALUE, so your core-pool-size never change nor scale. You must limit your capacity first before the thread-pool is scaled with maximal max-pool-size threads. In our example, we will scale when we reach 25 waiting requests. It will scale up to 20. When all threads are used in parallel the container throws an exception.
In the past SUN declared correctly: "That is exactly how it is supposed to behave. First the threads grow to coreSize, then the queue is used, then *if* the queue fills up then the number of threads expands from coreSize to maxSize. Hence if you use an unbounded queue the last part never happens. This is all described in the documentation. If you want an unbounded queue but more threads then increase the core size. Otherwise consider whether a bounded queue is more suitable to your needs."
Some extra information can be found here https://java.net/jira/browse/GLASSFISH-17735 and http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html.
The use of the asynchronous annotations is pretty well specified for beans but there are some pitfalls when it comes to REST services. Let's go through an example and check the behavior of a REST service with asynchronous methods as we go.
The use case is the following. We define a Resource and one Bean. The resource is a typical REST-resource with only one GET-method. The bean is a normal, stateless session bean which performs a long running task. This bean is pretty straightforward. We do not annotate the methods of the bean as asynchronous.
The first resource we build is pretty simple. We create an @Stateless resource and inject a @Suspended AsyncResponse. AsyncResponse takes care of the asynchronous response when the results become available.
When we open the browser and point to the URL of this resource we will see that the request is blocked for 10 seconds! But that is nothing new. Now, the problem is that we want to know how many threads are available to serve these requests. We are using a stateless bean, so we use the thread-pool of the ejb-container. This has some implications. When we use the http-thread-pool we will basically the same behavior, but we are not interested in the request thread. I want to scale out the ejb-pool. Adding beans to the pool is apparently not enough.
When you press F5 continuously in the browser, you will see something like "INFO: do a long task in thread: __ejb-thread-pool1" in the log. This number counts up and exceeds the threads in the http-thread-pool thanks to the AsyncResponse and @Suspended. But you will see (in a freshly installed domain) that the thread-pool does not exceed the limit of 16 even though you have max. 64 beans in your pool. We need to finetune the thread-pool of the ejb-container. But, you won't find any properties in the administrator console. You need to add them yourself. Open the domain.xml of your domain and add the following lines:
Now, rerun your application. You will see that the thread-pool goes up to 10 when you press F5 in the browser without holding it down. It seems to stagnate on 10 although you kinda specified a max-pool-size of 20. When you continuously press F5 you will suddenly see the threads go up to 20 before throwing an java.util.concurrent.RejectedExecutionException. Nice, but what the hell happened?
Let's dig deeper in the documentation of the thread pools:
thread-core-pool-size: Specifies the number of core threads in the EJB container’s common thread pool. The default value is 16. Great, there we have our number 16. Setting this to 10 oder 100 will change the actual number of threads doing some work.
thread-max-pool-size: Specifies the maximum number of threads in the EJB container’s common thread pool. The default value is 32. Nice, increasing this to 100 will be the maximum number of threads we can use? Yes and no. You have to consider the default-value of thread-queue-capacity.
thread-queue-capacity: Specifies the size of the thread pool queue, which stores new requests if more than thread-core-pool-size threads are running. The default value is the Integer.MAX_VALUE.
Here starts the confusion. Your queue-capacity is way too high. Pressing F5 will never reach MAX_VALUE, so your core-pool-size never change nor scale. You must limit your capacity first before the thread-pool is scaled with maximal max-pool-size threads. In our example, we will scale when we reach 25 waiting requests. It will scale up to 20. When all threads are used in parallel the container throws an exception.
In the past SUN declared correctly: "That is exactly how it is supposed to behave. First the threads grow to coreSize, then the queue is used, then *if* the queue fills up then the number of threads expands from coreSize to maxSize. Hence if you use an unbounded queue the last part never happens. This is all described in the documentation. If you want an unbounded queue but more threads then increase the core size. Otherwise consider whether a bounded queue is more suitable to your needs."
Some extra information can be found here https://java.net/jira/browse/GLASSFISH-17735 and http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html.
woensdag 8 mei 2013
Mounting Samba-share in Ubuntu
My DVD-reader gave up on me some time ago. I have two laptops with Ubuntu and wanted to use the DVD-reader from the other laptop on the first one. You can easily share the DVD-drive on one laptop using the properties from the file explorer. On the other side, you can see your laptop and the shared drive. But but but, you can't access the drive from some applications because they do not support Samba directly (which is rather evident). So, you need to mount the drive on a local directory. Just type:
sudo mount -t cifs -o username=yourname,password=yourpassword //your-ip-here/sharename mymount
The mymount directory must exist. Just create one with mkdir. I had trouble using the hostname instead of the IP. With the direct IP address, everything worked as planned. When you look into your mymount-directory you will see the content of your share. You can use this directory in every application.
sudo mount -t cifs -o username=yourname,password=yourpassword //your-ip-here/sharename mymount
The mymount directory must exist. Just create one with mkdir. I had trouble using the hostname instead of the IP. With the direct IP address, everything worked as planned. When you look into your mymount-directory you will see the content of your share. You can use this directory in every application.
Abonneren op:
Posts (Atom)