I’ve been doing experiments with JTables bound to database tables in the past. But I was not satisfied with the result to be honest. The pagination helps but there is still noticeable pauses each time a database query has to be issued. So I started looking into other possibilities.
I come up with the idea of doing lazy loading and presenting some fake data until the data is really retrieved from the database, I did a small proof of concept and seems to work ok.
The solution goes like this. It uses Beans Binding to bind a JTable to a custom List like in the previous post. This custom list (ResultListDerby in the example below) returns @Bean@s (the Bean is called Customer in the example) that are initially empty. By empty I mean that all its properties return something like “<data not retrieved from the database yet>”. So the JTable will be initially full of “<data not retrieved yet>”.
The picture above shows the JTable showing the List @of @Customers. Each row represents a Customer instance.
Having empty/fake Customer beans allow a fast drawing to screen but it’s not very useful. Now, if at the same point as each Customer is created we create SwingWorker and schedule it to run in a Executor then we can get something more meaningful. So what we do in the SwingWorker? The SwingWorker, you guessed it, will retrieve the data from the database and update the bean (look at ResultListDerby.getItem() method). When the bean (Customer.java) is updated it will notify its listeners of the changes, automatically by means of bound properties , in this case JTableBinding will be notified and the JTable that will repaint the cells to reflect the changes in the Bean. (Check how bound properties are implemented with of PropertyChangeSupport in Customer.java below). The rows will be updated one by one, as soon as the Executor completes a SwingWorker task a row will be updated.
This solution is free from annoying GUI freezes. The beans are always created fast because there is no need to go to the database to create them and that keeps the GUI liveness high. By moving the database access to @SwingWorker@s we keep the EDT (event dispatch thread) lightweight. The solution also avoids having too many running @SwingWorker@s at the same time by using a ExecutorService instead of executing them directly via the SwingWorker.execute() method (Check ResultListDerby.getItem() to see how it’s done).
Apparently blinklist doesn’t export bookmarks to JSON format any longer and delicious has changed authentication scheme for its delicious API for new accounts (now it forces new users to use the OAuth / Yahoo ID). So the solutions described in this old post of mine doesn’t work.
If you have a customized xhtml variant, like evernote ENML format and you want to render it with Flying Saucer R8 you must first make sure that the extra element (in ENML case, en-media) is defined as a block-level element. To do that you create your own NamespaceHandler and you make sure that you return "display: block;" for en-media in the implementation of NamespaceHandler.getNonCssStyling. (See ENMLNamespaceHandler.java below)
....
XHTMLPanel panel = new XHTMLPanel();
panel.setDocument(doc,"",new ENMLNamespaceHandler(new XhtmlNamespaceHandler()));
....
class ENMLNamespaceHandler implements NamespaceHandler {
....
public String getNonCssStyling(Element e) {
String toReturn = delegate.getNonCssStyling(e);
if ("en-media".equalsIgnoreCase(e.getNodeName())) {
toReturn = "display: block;";
}
return toReturn;
}
....
}
With that you ensure that xhtmlrenderer will call ReplacedElementFactory.createReplacedElement for en-media. Now you must supply a ReplacedElementFactory that it’s able to process en-media. Usually the implementation of the createReplacedElement() involves creating a Swing JComponent, wrapping it in a SwingReplacedElement and adding it to the LayoutContext.getCanvas().
....
ReplacedElementFactory cef = new ENMLReplacedElementFactory(new SwingReplacedElementFactory());
XHTMLPanel panel = new XHTMLPanel();
panel.getSharedContext().setReplacedElementFactory(cef);
panel.setDocument(doc,"",new ENMLNamespaceHandler(new XhtmlNamespaceHandler()));
....
public class ENMLReplacedElementFactory implements ReplacedElementFactory {
...
public ReplacedElement createReplacedElement(LayoutContext context, BlockBox box,
UserAgentCallback uac, int cssWidth, int cssHeight)
{
if ("en-media".equals(box.getElement().getNodeName())) {
JTextArea cc = new JTextArea();
cc.setText("Missing implementation for en-media");
cc.setSize(cc.getPreferredSize());
context.getCanvas().add(cc);
ReplacedElement toReturn = new SwingReplacedElement(cc) {
public boolean isRequiresInteractivePaint() {
return false;
}
};
return toReturn;
}
ReplacedElement toReturn = delegate.createReplacedElement(context, box, uac, cssWidth, cssHeight);
return toReturn;
}
....
}
iTunes was reporting a incorrect track time length for an audiobook that I created concatenating several mp3 together.
I had to reencode the whole thing again to make iTunes recognize propertly the track lenght. I could’t reencode the concatenated file itself as that ended up with a Segmentation fault in lame
cat *.mp3 |lame --mp3input - - >resultfile.mp3
cat *Night.mp3 |lame --mp3input - down.mp3
ID3v2 found. Be aware that the ID3 tag is currently lost when transcoding.
LAME 3.98.2 64bits (http://www.mp3dev.org/)
Using polyphase lowpass filter, transition band: 16538 Hz - 17071 Hz
Encoding <stdin> to down.mp3
Encoding as 44.1 kHz single-ch MPEG-1 Layer III (11x) 64 kbps qval=3
bitstream problem: resyncing...
bitstream problem: resyncing...
bitstream problem: resyncing...
bitstream problem: resyncing...
This uses the lame streaming mode, decodes the input stream (all mp3 concatenated) as mp3 and then reencodes it as mp3. Although it complains about “bitstream problem: resyncing...”, the resulting mp3 sounds fine.
java.io.FileNotFoundException: /Users/ecerulm/NetBeansProjects/en4j/NBPlatformApp/DTD/xhtml1-strict.dtd (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.(FileInputStream.java:106)
at java.io.FileInputStream.(FileInputStream.java:66)
at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:70)
at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:161)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:653)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1315)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startDTDEntity(XMLEntityManager.java:1282)
at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.setInputSource(XMLDTDScannerImpl.java:283)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.dispatch(XMLDocumentScannerImpl.java:1193)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.next(XMLDocumentScannerImpl.java:1090)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:1003)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:225)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:283)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:124)
at com.rubenlaguna.en4j.NoteContentViewModule.NoteContentViewTopComponent.resultChanged(NoteContentViewTopComponent.java:141)
…
…
I just found out on that if you have a Intel® 945 or any modern Intel card and you monitor/display/screen appears rotated 90 degrees or upside down, etc you can restore it to it’s original position by pressing Ctrl-Alt-↓
To add a XJC task to a Netbeans build.xml you need to add a -pre-compile target to your build.xml. If it’s a netbeans module build.xml then you need to make compile depend on -pre-compile and projectized-common.compile (see example below). For regular Java Applications just define the -pre-compile target as the standard build.xml will call -pre-compile before compile. Then it’s just a matter of defining the <taskdef> with the proper classpath to the jaxb’s jars.
But it’s just simpler to take a look to an example (this one is for a Netbeans module build.xml:
<project name="com.rubenlaguna.en4j.jaxb" default="netbeans" basedir=".">
<description>Builds, tests, and runs the project com.rubenlaguna.en4j.jaxb.</description>
<import file="nbproject/build-impl.xml"/>
<target name="-pre-compile">
<path id="xjc.classpath">
<fileset dir="/Applications/NetBeans/NetBeans 6.7.app/Contents/Resources/NetBeans/ide11/modules/ext/jaxb/" includes="*.jar"/>
<!-- import the JAXB 2.1 library if this task is in java application build.xml. you can't access library classpath from
a module's build.xml
pathelement path="${libs.JAXB21.classpath}"/>
<pathelement path="${libs.JAXB_21.classpath}"/>
-->
</path>
<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
<classpath refid="xjc.classpath"/>
</taskdef>
<xjc destdir="src" package="com.rubenlaguna.en4j.jaxb.generated">
<schema dir="src" includes="**/*.xsd"/>
<produces dir="src/com/rubenlaguna/en4j/jaxb/generated" includes="* impl/*" />
</xjc>
</target>
<target name="compile" depends="-pre-compile,projectized-common.compile"/>
</project>
Are you getting a ClassCastException in a Netbeans Platform Application, when you are you sure that the class can be casted? Then check http://wiki.netbeans.org/PlainView.jsp?page=DevFaqModuleCCE. This is most likely the result of the the classes being loaded by different classloaders. So JAXBContextImpl cannot be cast to JAXBContext because that JAXBContext is from Classloader “A” and @JAXBContextImpl @can only be cast to @JAXBContext @from Classloader “B”.
SEVERE [global]
java.lang.ClassCastException: com.sun.xml.bind.v2.runtime.JAXBContextImpl cannot be cast to javax.xml.bind.JAXBContext
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:145)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:277)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:372)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:337)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:244)
at com.rubenlaguna.en4j.mainmodule.ImportEvernoteFile.actionPerformed(ImportEvernoteFile.java:65)
at org.openide.awt.AlwaysEnabledAction.actionPerformed(AlwaysEnabledAction.java:115)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2028)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2351)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.AbstractButton.doClick(AbstractButton.java:389)
at com.apple.laf.ScreenMenuItem.actionPerformed(ScreenMenuItem.java:95)
at java.awt.MenuItem.processActionEvent(MenuItem.java:627)
at java.awt.MenuItem.processEvent(MenuItem.java:586)
at java.awt.MenuComponent.dispatchEventImpl(MenuComponent.java:317)
at java.awt.MenuComponent.dispatchEvent(MenuComponent.java:305)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:638)
at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:104)
[catch] at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
BUILD SUCCESSFUL (total time: 28 minutes 5 seconds)
So this could happen for example if you have both woodstox in a Netbeans Library Wrapper module and you make you application dependent on ide11 ⇒ JAXB 2.1 Library .
In my case I was able to solve by just removing JAXB 2.1 Library from the application.