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...
dinsdag 30 juli 2013
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.
Ubuntu 12.10, 13.04 problem with libdvdnav4
I recently updated to 12.10 and made the jump to 13.04 shortly after that. Unfortunately, Handbrake refused scanning DVD due to an error in libdvdnav. Apparently something went wrong during the dsitribution upgrade. To get libdvdnav and Handbrake working again, just run:
sudo /usr/share/doc/libdvdread4/install-css.sh
Restart Handbrake and your DVDs can be read again....
sudo /usr/share/doc/libdvdread4/install-css.sh
Restart Handbrake and your DVDs can be read again....
maandag 15 april 2013
Moving on....
I am currently moving my old blog entries to this new blog. Some old posts will not be transferred because time and software also moved on. The old blog address will be abandoned and disappear in the near future.
ActiveMQ and Network Interfaces
When you are using ActiveMQ as a message broker, the need can arise to bind the queue listener to a specific network-interface. Although this is not very common and some argue that the OS should do the routing, you can face certain situations in which your software decides which network-interface SHOULD or MUST be used for the communication.
The reason could be that some communication-channels are expensive and the machine needs to switch network-interfaces on the fly because of you business logic. When the servers are not under your control you cannot simply change the OS routing tables.
There is a simple trick in ActiveMQ to select the network-interface to use, although you cannot find it in the manual -- but it is in the code. Just use the following scheme for the binding:
tcp://remote-queue-ip:61616@network-interface-ip:61616
You can also use other protocols, of course.
The reason could be that some communication-channels are expensive and the machine needs to switch network-interfaces on the fly because of you business logic. When the servers are not under your control you cannot simply change the OS routing tables.
There is a simple trick in ActiveMQ to select the network-interface to use, although you cannot find it in the manual -- but it is in the code. Just use the following scheme for the binding:
tcp://remote-queue-ip:61616@network-interface-ip:61616
You can also use other protocols, of course.
A basic outline of a workflow system using J2EE and CDI
For one of my customers, we needed a very simple workflow-framework which coordinates the flow between methods inside a J2EE6 application on Glassfish. The business required to implement the following simple logic:
- Create a job.
- When step 1 was successful, then start a job (which affects some thousand objects) and send an email
- End a job when step 2 was successfull.
- Mark the job as failed when one of the steps couldn't be completed due to the implemented business-logic.
- Provide a handler to handle exceptions.
Taking a fully fledged workflow-system was way over the top to solve this problem. The workflow will also remain unchanged; and when it is changed, the code needed to be altered to. We needed to come up with a simple workflow-management which is bound to transitions and methods.
So, first we decided to create an observer the change the transitions of the workflow-steps. This is basically a very simple method which alters the status and stores it in the database. The next step was to create some annotations to add to the methods which needed to be executed during a certain step. We annotate our workflow methods as follows:
@Asynchronous
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@Workflow
@WorkflowStep(from = Status.IDLE, to = Status.PROGRESS)
public void startJob(
@WorkflowActionHandler
@Observes(notifyObserver = Reception.ALWAYS,
during = TransactionPhase.AFTER_SUCCESS)
final JobWorkflowEvent event) {}
This straight-forward approach is very clean and simple. Basically it says that this method will be executed after the transition from a Status.IDLE to Status.PROGRESS. Although we use an enum here, you could take any arbitrary integer. Using the CDI annotations we get some additional power. This method will only be executed after the success of the previous step. Here you can combine the full power of CDI with some basic workflow concepts to create a nice system.
Now remains the problem of the transition handling. The transitions are handled in an interceptor which is marked by the @Workflow annotation.
@Interceptor @Workflow
public class WorkflowInterceptor {
}
This interceptor does not do much more than changing the transition state when the method pinged by CDI has the correct workflow-steps. It uses some reflection to figure that out and allows access to the method.
To handle exceptions, we introduce a new annotation:
@Asynchronous
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@Workflow @WorkflowException
public void excJob(
@WorkflowActionHandler
@Observes(notifyObserver = Reception.ALWAYS,
during = TransactionPhase.AFTER_FAILURE)
final JobWorkflowEvent event) {}
Whenever one step fails unexpected, control is transferred to this method where certains actions can be executed. We need this annotation to prevent other methods to pick this event up.
Using CDI together with some custom annotations really did the job and works fine.
Abonneren op:
Posts (Atom)