<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog @ SIB Visions &#187; WebEngine</title>
	<atom:link href="http://blog.sibvisions.com/tag/webengine/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.sibvisions.com</link>
	<description>Blog @ SIB Visions</description>
	<lastBuildDate>Mon, 30 Mar 2026 11:14:36 +0000</lastBuildDate>
		<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Our Live-Ticker implementation - World cup 2014</title>
		<link>https://blog.sibvisions.com/2014/06/16/our-live-ticker-implementation-world-cup-2014/</link>
		<comments>https://blog.sibvisions.com/2014/06/16/our-live-ticker-implementation-world-cup-2014/#comments</comments>
		<pubDate>Mon, 16 Jun 2014 11:51:33 +0000</pubDate>
		<dc:creator>rjahn</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[JavaFX]]></category>
		<category><![CDATA[WebEngine]]></category>
		<category><![CDATA[WebView]]></category>
		<category><![CDATA[World cup]]></category>

		<guid isPermaLink="false">http://blog.sibvisions.com/?p=2995</guid>
		<description><![CDATA[We got a lot of (positive) feedback for our live ticker in Packung! It's great to see actual results depending on the current score  
We started our live ticker in 2008 with a simple implementation in Java. The solution simply sniffed results from standard html pages. It was easy to get results because result [...]]]></description>
			<content:encoded><![CDATA[<p>We got a lot of (positive) feedback for our live ticker in Packung! It's great to see actual results depending on the current score <img src='https://blog.sibvisions.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>We started our live ticker in 2008 with a simple implementation in Java. The solution simply sniffed results from standard html pages. It was easy to get results because result pages didn't use Ajax. It was harder in 2010 and 2012 because Ajax was heavily used. But we found some pages without Ajax. </p>
<p><strong>What's the problem with Ajax?</strong> It's not possible to get the complete html content with one simple http request with Java. You need a "browser" that handles javascript and async calls.</p>
<p>We didn't find a html page with live results this year, which didn't use Ajax or Flash. So we thought about a clever solution because we won't pay for "free content". And of course, our betting game is free and we don't earn money. But <strong>what's a clever solution?</strong> The task is simple: Grab results from existing live-ticker website (be aware of Ajax) - but how?</p>
<p>The solution is simple: <strong>Use a browser</strong> <img src='https://blog.sibvisions.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>But Java doesn't offer a browser control, doesn't it? Yes, <strong>JavaFX does</strong>!</p>
<p>In 2008 we played around with QT webkit control of QT Jambi (but the project is not active) because it was a nice browser control. The problem was that it didn't work headless and our application server was a linux box without X-Server. This year, we had the same restrictions because our server is a linux box and still no X-Server. We thought that JavaFX could be the right solution for us...</p>
<p>BUT it doesn't work headless enough - not with latest release. It will be better in upcoming releases and/or custom JavaFX builds because there is a Glass windowing component called <a href="https://wiki.openjdk.java.net/display/OpenJFX/Monocle#Monocle-HowtorunMonocle">Monocle</a>. But this was the right challenge for us.</p>
<p>Our current solution runs on Linux, without a real X-Server. It's a JavaFX WebView/WebEngine that reads data from a public live-ticker. </p>
<p><strong>How our solution works?</strong></p>
<p>Install important linux packages:</p>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;">yum <span class="kw2">install</span> xorg-x11-server-Xvfb xorg-x11-xauth <span class="kw2">gcc</span> glib2 glib2-devel libtiff libtiff-devel libjpeg-devel cairo cairo-devel pango pango-devel redhat-lsb</div>
</div>
<p>optional if available</p>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;">yum <span class="kw2">install</span> redhat-lsb-graphics</div>
</div>
<p>Download and install ATK</p>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;"><span class="kw2">wget</span> <span class="kw2">ftp</span>:<span class="sy0">//</span>ftp.muug.mb.ca<span class="sy0">/</span>mirror<span class="sy0">/</span>centos<span class="sy0">/</span>6<span class="sy0">/</span>os<span class="sy0">/</span>x86_64<span class="sy0">/</span>Packages<span class="sy0">/</span>atk-1.30.0-1.el6.x86_64.rpm<br />
<span class="kw2">wget</span> <span class="kw2">ftp</span>:<span class="sy0">//</span>ftp.muug.mb.ca<span class="sy0">/</span>mirror<span class="sy0">/</span>centos<span class="sy0">/</span>6<span class="sy0">/</span>os<span class="sy0">/</span>x86_64<span class="sy0">/</span>Packages<span class="sy0">/</span>atk-devel-1.30.0-1.el6.x86_64.rpm<br />
rpm <span class="re5">-Uvh</span> <span class="sy0">*</span>.rpm</div>
</div>
<p>and GTK+</p>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;"><span class="kw2">wget</span> http:<span class="sy0">//</span>ftp.gnome.org<span class="sy0">/</span>pub<span class="sy0">/</span>gnome<span class="sy0">/</span>sources<span class="sy0">/</span>gtk+<span class="sy0">/</span>2.18<span class="sy0">/</span>gtk+-2.18.2.tar.gz<br />
<span class="kw2">tar</span> <span class="re5">-xvf</span> gtk+-2.18.2.tar.gz<br />
<span class="kw3">cd</span> gtk+-2.18.2<br />
.<span class="sy0">/</span>configure<br />
<span class="kw2">make</span><br />
<span class="kw2">make</span> <span class="kw2">install</span></div>
</div>
<p>Start Xvfb: </p>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;">Xvfb :<span class="nu0">99</span> <span class="sy0">&amp;</span></div>
</div>
<p>Start application:</p>
<div class="codesnip-container" >
<div class="bash codesnip" style="font-family:monospace;"><span class="co0">#!/bin/sh</span><br />
<span class="kw3">export</span> <span class="re2">DISPLAY</span>=:99<br />
<span class="kw3">export</span> <span class="re2">LD_LIBRARY_PATH</span>=<span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>lib<br />
.<span class="sy0">/</span>jdk1.8.0_05<span class="sy0">/</span>bin<span class="sy0">/</span>java <span class="re5">-jar</span> livescore.jar <span class="sy0">&gt;&gt;</span> liveupdate.log <span class="nu0">2</span><span class="sy0">&gt;&gt;</span> liveupdate_err.log <span class="sy0">&amp;</span></div>
</div>
<p>The application itself is trivial. It's a class with main method:</p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;"><span class="co3">/**<br />
&nbsp;* Starts the application.<br />
&nbsp;* <br />
&nbsp;* @param pArgs the application parameters<br />
&nbsp;*/</span><br />
<span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">void</span> main<span class="br0">&#40;</span><span class="kw3">String</span><span class="br0">&#91;</span><span class="br0">&#93;</span> pArgs<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">new</span> Livescore<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="co3">/**<br />
&nbsp;* Creates a new instance of &lt;code&gt;Livescore&lt;/code&gt; and starts the update procedure.<br />
&nbsp;*/</span><br />
<span class="kw1">public</span> Livescore<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">super</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; fxPanel <span class="sy0">=</span> <span class="kw1">new</span> JFXPanel<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; Platform.<span class="me1">runLater</span><span class="br0">&#40;</span><span class="kw1">new</span> <span class="kw3">Runnable</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> run<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fxPanel.<span class="me1">setScene</span><span class="br0">&#40;</span><span class="kw1">new</span> Scene<span class="br0">&#40;</span><span class="kw1">new</span> BorderPane<span class="br0">&#40;</span><span class="br0">&#41;</span>, 800, 600<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; browser <span class="sy0">=</span> <span class="kw1">new</span> SimpleBrowser<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; browser.<span class="me1">load</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; start<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>We need the JFXPanel because JavaFX needs a scene, otherwise it'll throw Exceptions. We don't need the instance for other things.</p>
<p>The SimpleBrowser class is similar to this snippet:</p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;"><span class="co3">/**<br />
&nbsp;* Loads the configured website.<br />
&nbsp;*/</span><br />
<span class="kw1">public</span> <span class="kw4">void</span> load<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>view <span class="sy0">==</span> <span class="kw2">null</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; view <span class="sy0">=</span> <span class="kw1">new</span> WebView<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; engine <span class="sy0">=</span> view.<span class="me1">getEngine</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; engine.<span class="me1">load</span><span class="br0">&#40;</span><span class="st0">&quot;http://live-ticker.url&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; engine.<span class="me1">reload</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>thCheck <span class="sy0">==</span> <span class="kw2">null</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; thCheck <span class="sy0">=</span> <span class="kw1">new</span> <span class="kw3">Thread</span><span class="br0">&#40;</span><span class="kw1">new</span> <span class="kw3">Runnable</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> run<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="kw3">Thread</span>.<span class="me1">currentThread</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">==</span> thCheck<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Platform.<span class="me1">runLater</span><span class="br0">&#40;</span><span class="kw1">new</span> <span class="kw3">Runnable</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> run<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkResults<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">Thread</span>.<span class="me1">sleep</span><span class="br0">&#40;</span>10000<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">catch</span> <span class="br0">&#40;</span><span class="kw3">InterruptedException</span> ie<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//stop</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thCheck <span class="sy0">=</span> <span class="kw2">null</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; thCheck.<span class="me1">start</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>That's it. We got two "silent" Exceptions </p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;">java.<span class="me1">lang</span>.<span class="kw3">NullPointerException</span><br />
&nbsp; at sun.<span class="me1">reflect</span>.<span class="me1">UnsafeFieldAccessorImpl</span>.<span class="me1">ensureObj</span><span class="br0">&#40;</span>UnsafeFieldAccessorImpl.<span class="me1">java</span><span class="sy0">:</span>57<span class="br0">&#41;</span><br />
&nbsp; at sun.<span class="me1">reflect</span>.<span class="me1">UnsafeObjectFieldAccessorImpl</span>.<span class="me1">get</span><span class="br0">&#40;</span>UnsafeObjectFieldAccessorImpl.<span class="me1">java</span><span class="sy0">:</span>36<span class="br0">&#41;</span><br />
&nbsp; at java.<span class="me1">lang</span>.<span class="me1">reflect</span>.<span class="kw3">Field</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="kw3">Field</span>.<span class="me1">java</span><span class="sy0">:</span><span class="nu0">387</span><span class="br0">&#41;</span><br />
&nbsp; at com.<span class="me1">sun</span>.<span class="me1">javafx</span>.<span class="me1">webkit</span>.<span class="me1">theme</span>.<span class="me1">ScrollBarThemeImpl</span>.<span class="me1">getFieldValue</span><span class="br0">&#40;</span>ScrollBarThemeImpl.<span class="me1">java</span><span class="sy0">:</span><span class="nu0">397</span><span class="br0">&#41;</span><br />
&nbsp;...</div>
</div>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;"><span class="kw3">Exception</span> in thread <span class="st0">&quot;JavaFX Application Thread&quot;</span> java.<span class="me1">lang</span>.<span class="kw3">NullPointerException</span><br />
&nbsp; at com.<span class="me1">sun</span>.<span class="me1">javafx</span>.<span class="me1">webkit</span>.<span class="me1">theme</span>.<span class="me1">ScrollBarThemeImpl</span>.<span class="me1">thumbPosition</span><span class="br0">&#40;</span>ScrollBarThemeImpl.<span class="me1">java</span><span class="sy0">:</span>267<span class="br0">&#41;</span><br />
&nbsp; at com.<span class="me1">sun</span>.<span class="me1">javafx</span>.<span class="me1">webkit</span>.<span class="me1">theme</span>.<span class="me1">ScrollBarThemeImpl</span>.<span class="me1">getThumbPosition</span><span class="br0">&#40;</span>ScrollBarThemeImpl.<span class="me1">java</span><span class="sy0">:</span>352<span class="br0">&#41;</span><br />
&nbsp; at com.<span class="me1">sun</span>.<span class="me1">webkit</span>.<span class="kw3">Timer</span>.<span class="me1">twkFireTimerEvent</span><span class="br0">&#40;</span><span class="kw1">Native</span> <span class="kw3">Method</span><span class="br0">&#41;</span><br />
&nbsp; at com.<span class="me1">sun</span>.<span class="me1">webkit</span>.<span class="kw3">Timer</span>.<span class="me1">fireTimerEvent</span><span class="br0">&#40;</span><span class="kw3">Timer</span>.<span class="me1">java</span><span class="sy0">:</span>66<span class="br0">&#41;</span><br />
&nbsp; at com.<span class="me1">sun</span>.<span class="me1">webkit</span>.<span class="kw3">Timer</span>.<span class="me1">notifyTick</span><span class="br0">&#40;</span><span class="kw3">Timer</span>.<span class="me1">java</span><span class="sy0">:</span><span class="nu0">47</span><span class="br0">&#41;</span><br />
&nbsp; at javafx.<span class="me1">scene</span>.<span class="me1">web</span>.<span class="me1">WebEngine</span>$PulseTimer$2.<span class="me1">pulse</span><span class="br0">&#40;</span>WebEngine.<span class="me1">java</span><span class="sy0">:</span><span class="nu0">1154</span><span class="br0">&#41;</span><br />
&nbsp; ...</div>
</div>
<p>after the application start, because of some scrolling problems, but these Exceptions had no effect (in our solution).</p>
<p>The solution would rock with a real headless JavaFX but it's ok for us.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.sibvisions.com/2014/06/16/our-live-ticker-implementation-world-cup-2014/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
