- answered 546 questions
- asked 46 questions
- participated across 609 tags (mainly java, unix, bash and xml)
- received 35 badges - 2 gold, 10 silver and 23 bronze
Saturday, January 22, 2011
stackoverflow - 10k rep
I've finally crossed the 10k reputation milestone on stackoverflow! I thought I'd take this opportunity to reflect back on my time as a member of this famous programming Q & A site.
Even though I was one of the first people to join stackoverflow when the beta version came out two years ago, I did not become an active participant until much more recently. I have found this site to be a great way of helping people with programming difficulties and also as a great learning resource. During my time here, I have:
Labels:
stackoverflow
Saturday, January 08, 2011
A Paginated JList
If you have a large
JList and don't want to scroll through it, it might be a better idea to "paginate" it i.e. display the list in "pages" of a few rows at a time and allow users to flip back and forth between them. To do this, I have written a Java Swing component called PaginatedList, which looks like this:
You pass in a JList and specify a page size (the page size is 10 in this example) and it returns a PaginatedList which you can add onto another JComponent as normal. The code is shown below:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListModel;
/**
* A paginated JList. Only displays a specific number of rows
* and allows you to page back and forth through the list.
* with the help of a toolbar.
*/
public class PaginatedList extends JPanel {
private final int pageSize;
private final JList list;
private final ListModel model;
private final int lastPageNum;
private int currPageNum;
private JLabel countLabel ;
private JButton first, prev, next, last;
/**
* @param list the source list
* @param pageSize the number of rows visible
*/
public PaginatedList(JList list, int pageSize) {
super();
this.pageSize = pageSize;
this.list = list;
this.model = list.getModel();
//work out how many pages there are
this.lastPageNum = model.getSize() / pageSize +
(model.getSize() % pageSize != 0 ? 1 : 0);
this.currPageNum = lastPageNum > 0 ? 1 : 0;
setLayout(new BorderLayout());
countLabel = new JLabel() ;
add(countLabel, BorderLayout.NORTH);
add(list, BorderLayout.CENTER);
add(createControls(), BorderLayout.SOUTH);
updatePage();
}
private JPanel createControls() {
first = new JButton(new AbstractAction("<<") {
public void actionPerformed(ActionEvent e) {
currPageNum = 1;
updatePage();
}
});
prev = new JButton(new AbstractAction("<") {
public void actionPerformed(ActionEvent e) {
if (--currPageNum <= 0)
currPageNum = 1;
updatePage();
}
});
next = new JButton(new AbstractAction(">") {
public void actionPerformed(ActionEvent e) {
if (++currPageNum > lastPageNum)
currPageNum = lastPageNum;
updatePage();
}
});
last = new JButton(new AbstractAction(">>") {
public void actionPerformed(ActionEvent e) {
currPageNum = lastPageNum;
updatePage();
}
});
JPanel bar = new JPanel(new GridLayout(1, 4));
bar.add(first);
bar.add(prev);
bar.add(next);
bar.add(last);
return bar;
}
private void updatePage() {
//replace the list's model with a new model containing
//only the entries in the current page.
if(model.getSize() != 0){
final DefaultListModel page = new DefaultListModel();
final int start = (currPageNum - 1) * pageSize;
int end = start + pageSize;
if (end >= model.getSize()) {
end = model.getSize();
}
for (int i = start; i < end; i++) {
page.addElement(model.getElementAt(i));
}
list.setModel(page);
}
//update the label
countLabel.setText("Page " + currPageNum + "/" + lastPageNum);
// update buttons
final boolean canGoBack = currPageNum > 1;
final boolean canGoFwd = currPageNum != lastPageNum;
first.setEnabled(canGoBack);
prev.setEnabled(canGoBack);
next.setEnabled(canGoFwd);
last.setEnabled(canGoFwd);
}
public static void main(String args[]) throws Exception {
// create 100 elements of dummy data.
String[] data = new String[101];
for (int i = 0; i < data.length; i++) {
data[i] = "Item "+ (i + 1);
}
// create a paginated list with page size 20
PaginatedList list = new PaginatedList(new JList(data), 10);
// add it to a frame
JFrame f = new JFrame("Paginated List Demo");
f.add(list);
f.setSize(100, 100);
f.pack();
f.setVisible(true);
}
}
Labels:
Java,
programming,
swing
Saturday, January 01, 2011
fahd.blog in 2010
Happy 2011!
I'd like to wish everyone a great start to an even greater new year! During 2010, I posted 47 new entries on fahd.blog, which is 23% more than in 2009. In addition to more posts, I am thrilled that I have more readers from all over the world too! Thanks for reading! Top 5 posts of 2010: I'm going to be writing a lot more this year, so stay tuned for more great techie tips, tricks and hacks! :)
I'd like to wish everyone a great start to an even greater new year! During 2010, I posted 47 new entries on fahd.blog, which is 23% more than in 2009. In addition to more posts, I am thrilled that I have more readers from all over the world too! Thanks for reading! Top 5 posts of 2010: I'm going to be writing a lot more this year, so stay tuned for more great techie tips, tricks and hacks! :)
Saturday, December 18, 2010
Automatically Retry Failed Jobs in Quartz
How do you handle job failures in Quartz? There are a few things you can do:
If you want to keep trying over and over again until the job succeeds, all you have to do is throw a
It gets a bit more complicated if you want to retry a certain number of times only. You have to use a
- Do nothing. Let the job fail and log the error.
- Retry continuously until the job succeeds.
- Retry n times and then disable the job.
If you want to keep trying over and over again until the job succeeds, all you have to do is throw a
JobExecutionException with a flag to tell the scheduler to fire it again when it fails. The following code shows how:
class MyJob implements Job {
public MyJob() {
}
public void execute(JobExecutionContext context)
throws JobExecutionException {
try{
//do something
}
catch(Exception e){
Thread.sleep(10000); //sleep for 10 secs
JobExecutionException e2 = new JobExecutionException(e);
//fire it again
e2.refireImmediately();
throw e2;
}
}
}
Retrying n times:It gets a bit more complicated if you want to retry a certain number of times only. You have to use a
StatefulJob and hold a retryCounter in its JobDataMap, which you increment if the job fails. If the counter exceeds the maximum number of retries, then you can disable the job if you wish.
class MyJob implements StatefulJob {
public MyJob() {
}
public void execute(JobExecutionContext context)
throws JobExecutionException {
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
int count = dataMap.getIntValue("count");
// allow 5 retries
if(count >= 5){
JobExecutionException e = new JobExecutionException("Retries exceeded");
//unschedule it so that it doesn't run again
e.setUnscheduleAllTriggers(true);
throw e;
}
try{
//do something
//reset counter back to 0
dataMap.putAsString("count", 0);
}
catch(Exception e){
count++;
dataMap.putAsString("count", count);
JobExecutionException e2 = new JobExecutionException(e);
Thread.sleep(10000); //sleep for 10 secs
//fire it again
e2.refireImmediately();
throw e2;
}
}
}
Labels:
exceptions,
Java,
programming,
quartz
Saturday, December 11, 2010
Throw a checked exception from a method without declaring it
When you try to throw a checked exeption from a method in Java, the compiler will force you to either catch it or declare it to be thrown in the method declaration. For example, the following method fails to compile:
Avoiding Checked Exceptions [O'Reilly]
public void go(){
throw new IOException();
}
The compiler says:
Dummy.java:15: unreported exception java.io.IOException;
must be caught or declared to be thrown
throw new IOException();
^
1 error
However, if you declare it to be thrown in the method declaration, like this:
public void go() throws IOException{
throw new IOException();
}
then it compiles successfully.
But is it possible to throw a checked exception WITHOUT declaring it to be thrown? You could wrap it in a RuntimeException (for example, new RuntimeException(new IOException()), but then you lose the ability to catch the checked exception in the caller method, because you have changed the type of the exception.
There is another trick you can use. I first noticed this being done in the JDK's java.lang.Class#newInstance0 method:
private T newInstance0()
throws InstantiationException, IllegalAccessException
{
...
// Run constructor
try {
return tmpConstructor.newInstance((Object[])null);
} catch (InvocationTargetException e) {
Unsafe.getUnsafe().throwException(e.getTargetException());
// Not reached
return null;
}
...
}
As shown above, the method throws an InvocationTargetException but only declares the exceptions InstantiationException and IllegalAccessException to be thrown! The Sun utility class sun.misc.Unsafe is being used to throw a checked exception without declaring it. We could use the same approach, but unfortunately our code throws a security exception when we try to use it: java.lang.SecurityException: Unsafe. However, we can bypass this by using reflection to get hold of the unsafe variable directly, as shown below:
public void go() {
getUnsafe().throwException(new IOException());
}
private Unsafe getUnsafe() {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
So, why did the JDK developers do it this way? I don't know, but I'm sure they had a good reason. Although this is a neat trick to impress your friends, I wouldn't recommend using it. This is non-standard, undocumented, Sun-specific code which could change in future releases and may not be compatible with all JVMs. It also makes code harder to understand for others and violates the POLA.
Further Reading:Avoiding Checked Exceptions [O'Reilly]
Labels:
exceptions,
Java,
programming
Subscribe to:
Posts (Atom)
