Dmitriy Sukharev. IT Bloghttp://sukharevd.net/2014-04-01T06:02:00+03:00Install Oracle JDK 8 under Linux in couple minutes2014-04-01T06:02:00+03:00Dmitriy Sukharevtag:sukharevd.net,2014-04-01:install-oracle-jdk-under-linux.html<p>We were waiting for Java 8 so long, and finally it's ready with all its
ground-breaking new features.</p>
<p>This article will help you to install or update Oracle JDK 8 under Linux.
I've tested it with several Linux distributions including Debian Wheezy, Jessie,
Ubuntu 12.04, 13.10, 14.04, CentOS 6.4, Mint 16 and Fedora 20.</p>
<p>To make installation as easy for you as possible I wrote JDK installation script. But since
Oracle requires you to accept license before downloading binaries,
installation consists of 2 steps: </p>
<ol>
<li>Download JDK as tar.gz file from
<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Oracle's website</a>.</li>
<li>
<p>In terminal go to the directory with downloaded tar.gz file, and execute the following commands as sudoer:</p>
<div class="highlight"><pre>wget http://sukharevd.net/static/files/blog/oracle-jdk/oracle-jdk-install.sh -O oracle-jdk-install.sh
sudo bash oracle-jdk-install.sh
</pre></div>
</li>
</ol>
<p>Let me bring some light to this mysterious command explaining what is gonna happen.
The command will download and run my installation script which scans
current directory for JDK tarballs and selects the latest one (based on name). After that it
extracts tarball, updates environment variables and updates alternatives. The
cool thing is if you already have JDK installed from repository, it will not
override JDK installed by script. So you shouldn't be afraid to install packages
from repository that have dependencies to OpenJDK.</p>
<p>Be aware that terminal sessions opened before installation still might
show old version of java. If it's so, try to open a new terminal.</p>
<p>Among the last lines of this command's output you should see something like</p>
<div class="highlight"><pre>java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)
</pre></div>
<p>If so, congratulations! Oracle JDK 8 has been successfully installed and you can
enjoy cool features of new JDK release.</p>Backing up partitions over network with FSArchiver2013-12-23T08:18:00+02:00Dmitriy Sukharevtag:sukharevd.net,2013-12-23:backing-up-partitions-over-network-with-fsarchiver.html<p>Use case in a nutshell: One your host have a partition to backup, there's the second host under Linux with enought free space, you want to do backup to this remote Linux host.</p>
<p>OK, let's start with a warning. Backup and restore might be dangerous operations that potentially can cause loose
of data. There's a lot of things that can go wrong, especially while streaming over network. Also it's necessary to be
very careful executing these operations in so manual way as described below. There should be some paid services that
reduce risks of loosing data. I use described approach only because I have enough space for backups on my desktop, do
redundant backups, don't want to use paid services (just because I can do it by my own) and don't backup any business
related data. Thankfully I have never lost my data for about 7 years of using backup/restore tools.</p>
<p>In the previous article I described <a target="_blank" href="http://sukharevd.net/making-backups-of-ext4-partitions-with-fsarchiver.html">
Making backups of ext4 partitions with FSArchiver</a>. In this one I'm introducing Network File System (NFS) to make it
possible to do remote backups. The whole process can be divided to 3 steps:</p>
<ol>
<li>Set up NFS server.</li>
<li>Set up NFS client.</li>
<li>Back up/Restore with FSArchiver.</li>
</ol>
<p>You will need:</p>
<ol>
<li>Linux host with enough space to store backups.</li>
<li>Linux Live CD run on host whose partition need to be backed up.</li>
<li>Understand of what you are doing.</li>
</ol>
<p>The scripts below were tested with Debian Wheezy and Ubuntu 12.04 and need to be modified if for non-Debian like Linux
distributions that doesn't have apt command.</p>
<h2>Setting up NFS Server</h2>
<p>NFS server should be installed and configured on Linux machine that you want to use for actual storage of backups.
Configuration is quite primitive and insecure, so be sure that you trust the network you use. Here is
<a target="_blank" href="http://sukharevd.net/static/files/blog/remote-backup/nfs-server.sh">example bash
script to install NFS server</a>. You need to specify the location where you want backups to be stored and limit access
by IP or network address (in example below only hosts from network 192.168.56.0/24 can access NFS server).</p>
<div class="highlight"><pre><span class="nv">BACKUP_DIR</span><span class="o">=</span><span class="s2">"/backups"</span> <span class="c"># Change me if necessary</span>
<span class="nv">CLIENTS</span><span class="o">=</span><span class="s2">"192.168.56.0/24"</span> <span class="c"># Change me</span>
<span class="nv">EXPORTS_RECORD</span><span class="o">=</span><span class="s2">"$BACKUP_DIR $CLIENTS(rw,sync,no_subtree_check)"</span>
sudo apt-get install nfs-kernel-server nfs-common
<span class="o">[</span> ! -d <span class="nv">$BACKUP_DIR</span> <span class="o">]</span> <span class="o">&&</span> sudo mkdir -p <span class="nv">$BACKUP_DIR</span>
sudo chmod 777 <span class="nv">$BACKUP_DIR</span>
sudo chown nobody:nogroup <span class="nv">$BACKUP_DIR</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"`tail -n1 /etc/exports`"</span> !<span class="o">=</span> <span class="s2">"$EXPORTS_RECORD"</span> <span class="o">]</span>; <span class="k">then</span>
<span class="k"> </span>sudo sh -c <span class="s2">"echo \"$EXPORTS_RECORD\" >> /etc/exports"</span>
<span class="k">fi</span>
sudo exportfs -a
sudo service nfs-kernel-server restart
</pre></div>
<p>Unfortunately it's often necessary to reboot host after execution of these commands, so the host really need to
be Linux host, you would not be able to use some live CD.</p>
<p>You also might consider removing nfs-kernel-server package if you don't need NFS server after creation backups. </p>
<h2>Setting up NFS client</h2>
<p>NFS client should be installed and configured on machine that have partitions to be backed up. FSArchiver is a Linux
tool and should be run in Linux. Although it doesn't mean that you need Linux to be installed, you can use live CDs
like Debian live-CD or Ubuntu live-CD (examples below were tested with these two). Here is
<a target="_blank" href="http://sukharevd.net/static/files/blog/remote-backup/nfs-client.sh"> the example bash script
to install NFS client</a>. You need to specify NFS server IP address and the same directory you specified while setting
up server as remote directory.</p>
<div class="highlight"><pre><span class="nv">SERVER_IP</span><span class="o">=</span>192.168.56.1 <span class="c"># Change me</span>
<span class="nv">REMOTE_DIR</span><span class="o">=</span><span class="s2">"/backups"</span> <span class="c"># Change me if necessary</span>
<span class="nv">LOCAL_DIR</span><span class="o">=</span><span class="s2">"/mnt/nfs/backups"</span>
<span class="nv">FSTAB_RECORD</span><span class="o">=</span><span class="s2">"$SERVER_IP:$REMOTE_DIR $LOCAL_DIR nfs rw,async,nodev,nosuid,user 0 0"</span>
sudo apt-get update
sudo apt-get install nfs-common
<span class="o">[</span> ! -d <span class="nv">$LOCAL_DIR</span> <span class="o">]</span> <span class="o">&&</span> sudo mkdir -p <span class="nv">$LOCAL_DIR</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"`tail -n1 /etc/fstab`"</span> !<span class="o">=</span> <span class="s2">"$FSTAB_RECORD"</span> <span class="o">]</span>; <span class="k">then</span>
<span class="k"> </span>sudo sh -c <span class="s2">"echo $FSTAB_RECORD >> /etc/fstab"</span>
<span class="k">fi</span>
sudo mount <span class="nv">$LOCAL_DIR</span>
df -h
</pre></div>
<h2>Making backup</h2>
<p>Finally it's necessary to install fsarchiver (in Ubuntu live CD it might be necessary to enable universe repository
first) </p>
<div class="highlight"><pre>sudo apt-get install nfs-common fsarchiver
</pre></div>
<p>and run it for backing up, for instance:</p>
<div class="highlight"><pre>sudo fsarchiver -j4 -z5 -L<span class="s2">"Ubuntu 12.04. (/dev/sda1)"</span> -s2037 savefs <span class="se">\</span>
/mnt/nfs/backups/ubuntu20131218.fsa /dev/sda1
</pre></div>
<p>Here /dev/sda1 partition will be backed up in 4 threads with compression rate equal to 5 (max is 9), it will have the
specified label, splitted to files of 2037MB, with the first part named as /mnt/nfs/backups/ubuntu20131218.fsa. Output
for this command:</p>
<div class="highlight"><pre>Archive will be split into volumes of 2135949312 bytes (1.99 GB)
Statistics for filesystem 0
* files successfully processed:....regfiles=87985, directories=13675, symlinks=53530, hardlinks=0, specials=82
* files with errors:...............regfiles=0, directories=0, symlinks=0, hardlinks=0, specials=0
</pre></div>
<p>While error counters are 0 you are OK.</p>
<p>But how have I determined that I need to backup /dev/sda1 partition? I used <code>df -h</code> command to determine partition by
it's size and used/available space.</p>
<p>Also consider creating checksum to ensure that backup wasn't corrupted after creation.</p>
<h2>Restore backup</h2>
<p>Before restore (and/or after backing up) you might want to get some information about created backup archive. To get
it run in terminal fsarchiver with command archinfo as shown below (with output)</p>
<div class="highlight"><pre>fsarchiver archinfo /mnt/nfs/backups/ubuntu20131218.fsa
====================== archive information ======================
Archive type: filesystems
Filesystems count: 1
Archive id: 52b17c45
Archive file format: FsArCh_002
Archive created with: 0.6.12
Archive creation date: 2013-12-19_04-13-31
Archive label: Ubuntu 12.04. (/dev/sda1)
Minimum fsarchiver version: 0.6.4.0
Compression level: 5 (bzip2 level 2)
Encryption algorithm: none
===================== filesystem information ====================
Filesystem id in archive: 0
Filesystem format: ext4
Filesystem label:
Filesystem uuid: 64c0f523-21f8-41fd-be4c-dd2950fa0204
Original device: /dev/sda1
Original filesystem size: 10.70 GB (11490541568 bytes)
Space used in filesystem: 2.41 GB (2592837632 bytes)
</pre></div>
<p>From the output you need to determine filesystem id in archive. If you created backup with only one partition inside
(as shown below) then ID should always be 0, but it never hurts to check.</p>
<p>Then determine the partition to where you want this backup be restored with <code>df -h</code> command as described in the end
of previous section. All data at this partition will be overwritten by backup.</p>
<p>To restore backup run fsarchiver with <code>restfs</code> command as shown below (followed with output):</p>
<div class="highlight"><pre>sudo fsarchiver restfs /mnt/nfs/backups/ubuntu20131218.fsa id=0,dest=/dev/sda1
Statistics for filesystem 0
* files successfully processed:....regfiles=87985, directories=13675, symlinks=53530, hardlinks=0, specials=82
* files with errors:...............regfiles=0, directories=0, symlinks=0, hardlinks=0, specials=0
</pre></div>Encrypt your sensitive data in command line under Linux2013-11-12T22:01:00+02:00Dmitriy Sukharevtag:sukharevd.net,2013-11-12:encrypt-your-sensitive-data-in-command-line-under-linux.html<p>Do you store your passwords, PIN codes, bank account information, SSN or other sensitive data in the text file at your hard drive?
Hope not. But it's very difficult to hold all that stuff in memory. Instead it would be nice to encrypt it. One option could be to choose utility
like TrueCrypt, but it implies mounting volumes, having a bunch of files and not forgetting to unmount volumes.
Instead I suggest having sensitive data encrypted in command line easily like <code>encr filename</code> and <code>decr filename</code>.
For this purpose let's take a look at <a target="_blank" href="http://www.gnupg.org/">GPG</a> and
<a target="_blank" href="http://www.openssl.org/">OpenSSL</a> utilities.</p>
<h2>The GNU Privacy Guard</h2>
<p>To encrypt your data with GPG you can use either keypair or passphrase. I'm gonna show here keypair way.
If you need encrypt using only passphrase, refer to man page for gpg, you are interested in -c option.</p>
<p>To generate new key execute command:</p>
<div class="highlight"><pre>gpg --gen-key
</pre></div>
<p>Tool will ask you several questions in interactive mode. If you don't know that to answer, select default answer. Don't left passphrase empty.
You will also be asked to input your email address. Please specify the same email while encryption:</p>
<div class="highlight"><pre><span class="nb">echo</span> <span class="s2">"Sensitive data"</span> | gpg -e -r email@example.com -o ~/cipher
</pre></div>
<p>The string "Sensitive data" will be encrypted using your key and written to file ~/cipher. If you need to encrypt the multiline text, skip
echo command (start with gpg -e...), run command, input your text and finally press <code>Ctrl+D</code> to finish input.</p>
<p>To decrypt text run:</p>
<div class="highlight"><pre>gpg -d ~/cipher
</pre></div>
<p>You will see your encrypted text.</p>
<h2>OpenSSL</h2>
<p>Alternative way could be to use OpenSSL.</p>
<p>First of all let's generate private key:</p>
<div class="highlight"><pre>mkdir ~/.openssl
chmod 700 ~/.openssl
openssl genrsa -out ~/.openssl/my.private 4096
chmod 600 ~/.openssl/my.private
</pre></div>
<p>To encrypt string:</p>
<div class="highlight"><pre><span class="nb">echo</span> <span class="s2">"Sensitive data"</span> | openssl rsautl -inkey ~/.openssl/my.private -encrypt > ~/cipher
</pre></div>
<p>To decrypt string:</p>
<div class="highlight"><pre>openssl rsautl -inkey ~/.openssl/my.private -decrypt < ~/cipher
</pre></div>Making Jersey-based web-services be JSONP friendly2013-10-06T08:18:00+03:00Dmitriy Sukharevtag:sukharevd.net,2013-10-06:making-web-services-be-jsonp-friendly.html<p>It's pretty easy to make web-services answer with JSONP callbacks if you're
using Jersey. Adding single filter you can make all web-services' resources
add callbacks to their response.</p>
<p>Here is the code of such filter. Note that it's Jersey-based.</p>
<div class="highlight"><pre><span class="kn">package</span> <span class="n">net</span><span class="o">.</span><span class="na">sukharevd</span><span class="o">.</span><span class="na">ws</span><span class="o">.</span><span class="na">rs</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.ws.rs.core.GenericEntity</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.ws.rs.core.MediaType</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.ws.rs.core.Response</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.sun.jersey.api.json.JSONWithPadding</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.sun.jersey.spi.container.ContainerRequest</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.sun.jersey.spi.container.ContainerResponse</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.sun.jersey.spi.container.ContainerResponseFilter</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Filter that optionally wraps a JSON response in a JSONP callback.</span>
<span class="cm"> * <p/></span>
<span class="cm"> * For this wrapping to happen two things need to be true:</span>
<span class="cm"> * <ul></span>
<span class="cm"> * <li>The Media type of the response must be set to JSON or application/javascript</li></span>
<span class="cm"> * <li>The request must have a query parameter called {@code callback}</li></span>
<span class="cm"> * </ul></span>
<span class="cm"> * <p/></span>
<span class="cm"> *</span>
<span class="cm"> * @see <a href="http://weblogs.java.net/blog/felipegaucho/archive/2010/02/25/jersey-feat-jquery-jsonp">JSONP with</span>
<span class="cm"> * Jersey and jQuery</a></span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">JsonpResponseFilter</span> <span class="kd">implements</span> <span class="n">ContainerResponseFilter</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">ContainerResponse</span> <span class="nf">filter</span><span class="o">(</span><span class="n">ContainerRequest</span> <span class="n">request</span><span class="o">,</span> <span class="n">ContainerResponse</span> <span class="n">response</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">response</span><span class="o">.</span><span class="na">getMediaType</span><span class="o">()</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">||</span> <span class="o">!</span><span class="n">response</span><span class="o">.</span><span class="na">getMediaType</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="n">MediaType</span><span class="o">.</span><span class="na">APPLICATION_JSON_TYPE</span><span class="o">)</span>
<span class="o">&&</span> <span class="o">!</span><span class="n">response</span><span class="o">.</span><span class="na">getMediaType</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="k">new</span> <span class="n">MediaType</span><span class="o">(</span><span class="s">"application"</span><span class="o">,</span> <span class="s">"javascript"</span><span class="o">))</span>
<span class="o">&&</span> <span class="o">!</span><span class="n">response</span><span class="o">.</span><span class="na">getMediaType</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="k">new</span> <span class="n">MediaType</span><span class="o">(</span><span class="s">"application"</span><span class="o">,</span> <span class="s">"x-javascript"</span><span class="o">)))</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">response</span><span class="o">;</span>
<span class="o">}</span>
<span class="n">String</span> <span class="n">callback</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="na">getQueryParameters</span><span class="o">().</span><span class="na">getFirst</span><span class="o">(</span><span class="s">"callback"</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">callback</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">||</span> <span class="n">callback</span><span class="o">.</span><span class="na">isEmpty</span><span class="o">())</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">response</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">if</span> <span class="o">(</span><span class="n">response</span><span class="o">.</span><span class="na">getEntity</span><span class="o">()</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&&</span> <span class="n">response</span><span class="o">.</span><span class="na">getEntity</span><span class="o">().</span><span class="na">getClass</span><span class="o">()</span> <span class="o">!=</span> <span class="n">GenericEntity</span><span class="o">.</span><span class="na">class</span>
<span class="o">&&</span> <span class="n">response</span><span class="o">.</span><span class="na">getEntity</span><span class="o">().</span><span class="na">getClass</span><span class="o">()</span> <span class="o">!=</span> <span class="n">JSONWithPadding</span><span class="o">.</span><span class="na">class</span><span class="o">)</span> <span class="o">{</span>
<span class="nd">@SuppressWarnings</span><span class="o">(</span><span class="s">"unchecked"</span><span class="o">)</span>
<span class="kd">final</span> <span class="n">GenericEntity</span><span class="o"><?></span> <span class="n">genericEntity</span> <span class="o">=</span> <span class="k">new</span> <span class="n">GenericEntity</span><span class="o">(</span><span class="n">response</span><span class="o">.</span><span class="na">getEntity</span><span class="o">(),</span> <span class="n">response</span><span class="o">.</span><span class="na">getEntityType</span><span class="o">());</span>
<span class="n">JSONWithPadding</span> <span class="n">jsonp</span> <span class="o">=</span> <span class="k">new</span> <span class="n">JSONWithPadding</span><span class="o">(</span><span class="n">genericEntity</span><span class="o">,</span> <span class="n">callback</span><span class="o">);</span>
<span class="n">response</span><span class="o">.</span><span class="na">setEntity</span><span class="o">(</span><span class="n">jsonp</span><span class="o">);</span>
<span class="n">response</span><span class="o">.</span><span class="na">setResponse</span><span class="o">(</span><span class="n">Response</span><span class="o">.</span><span class="na">fromResponse</span><span class="o">(</span><span class="n">response</span><span class="o">.</span><span class="na">getResponse</span><span class="o">())</span>
<span class="o">.</span><span class="na">type</span><span class="o">(</span><span class="s">"application/javascript"</span><span class="o">)</span>
<span class="o">.</span><span class="na">entity</span><span class="o">(</span><span class="n">jsonp</span><span class="o">).</span><span class="na">build</span><span class="o">());</span>
<span class="k">return</span> <span class="n">response</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">return</span> <span class="n">response</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>You can add this filter to web.xml as easy as adding parameter</p>
<div class="highlight"><pre><span class="nt"><init-param></span>
<span class="nt"><param-name></span>com.sun.jersey.spi.container.ContainerResponseFilters<span class="nt"></param-name></span>
<span class="nt"><param-value></span>net.sukharevd.ws.rs.JsonpResponseFilter<span class="nt"></param-value></span>
<span class="nt"></init-param></span>
</pre></div>
<p>or if you use GrizzlyServerFactory</p>
<div class="highlight"><pre><span class="n">ResourceConfig</span> <span class="n">rc</span> <span class="o">=</span> <span class="k">new</span> <span class="n">PackagesResourceConfig</span><span class="o">(</span><span class="s">"net.sukharevd.ws.rs"</span><span class="o">);</span>
<span class="n">rc</span><span class="o">.</span><span class="na">getContainerResponseFilters</span><span class="o">().</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="n">JsonpResponseFilter</span><span class="o">());</span>
<span class="n">HttpServer</span> <span class="n">httpServer</span> <span class="o">=</span> <span class="n">GrizzlyServerFactory</span><span class="o">.</span><span class="na">createHttpServer</span><span class="o">(</span><span class="n">BASE_URI</span><span class="o">,</span> <span class="n">rc</span><span class="o">);</span>
</pre></div>
<p><a target="_blank" href="https://github.com/sukharevd/jsonp-filter-example">Here</a>
you can find GitHub repository with web-services and GWT-client sample projects.</p>Gzipping website in Amazon S3 bucket2013-09-12T07:03:00+03:00Dmitriy Sukharevtag:sukharevd.net,2013-09-12:gzipping-website-in-amazon-s3-bucket.html<p>Amazon S3 enables users to create static websites easily. It goes without saying that as far as websites are static
there's no server related "sugar" like dynamic HTTP headers that depends on user's request. Unfortunately it
also means that S3 service can't respond with either compressed or uncompressed page response depending on request.</p>
<p>At the same time modern webpages grow constantly, one with jQuery and Bootstraps can easily reach 300+KB. Downloading
several files can aggravate response time yet more. Search engines penalize sites with big latency, and no matter
how fast your server is it most likely will not decrease latency as much as compression does. And it concerns not
only search engines, it's quite reasonable - bad response time makes users unhappy. Do you remember how you feel
when your OS loads several minutes? It's the same.</p>
<p>So lack of compression sucks. Really. And no, I don't know a way to make S3 work as web server. But it doesn't matter.
Can you name a browser that doesn't support Gzip compression? Do you know someone who uses it? Personally I don't.
Even lynx supports gzipped responses. So most likely nothing bad happens if we make our site Gzipped only. Yes, I know,
I dreamed about better solution too, but it's the best I've found so far. If you can suggest something better, please
contact me, I will be happy to hear about your approach. Meanwhile Gzipping webpages before submitting them to S3
bucket works for me now quite good and I'm going to describe how I manage to use it.</p>
<p>And finally another bad news (last ones I promise) - several repeating gzipping of the same file have different hash sums. At
the same time tools like <code>s3cmd</code> execute synchronization of bucket with local directory based on hash sums and objects'
size. This means that you can't gzip the whole site every time you update some page. Actually you can, but it will
require manual synchronization with bucket that is huge pain in the ass, or it will cause useless synchronization of
unchanged pages you should pay for.</p>
<p><strong>So what do I suggest?</strong> Automated synchronization of changed only files. For this purpose I suppose having two directories:
one with latest uncompressed content, and another with published gzipped content. Before publication latest content is
compared with extracted gzipped one, and if they are different latest one will be compressed and will replace gzipped
one in the second directory. And if they are the same, nothing will happen, and gzipped page will not be changed as
it's supposed. In such a way only changed pages will be synchronized by s3cmd.</p>
<p>As static site generator I use <a target="_blank" href="http://blog.getpelican.com/">Pelican</a>, so my website is
build with <code>make</code>. Finally deploying to Amazon S3 will affect these targets:</p>
<div class="highlight"><pre><span class="nf">compress</span><span class="o">:</span>
python tools/aws-s3-gzip-compression.py <span class="k">$(</span>OUTPUTDIR<span class="k">)</span> <span class="k">$(</span>S3_PUBLICATION_DIR<span class="k">)</span>
<span class="nf">s3_gzip_upload</span><span class="o">:</span> <span class="m">publish compress </span>
s3cmd sync <span class="k">$(</span>S3_PUBLICATION_DIR<span class="k">)</span>/ s3://<span class="k">$(</span>S3_BUCKET<span class="k">)</span> --acl-public --add-header <span class="se">\</span>
<span class="s2">"Content-Encoding:gzip"</span> --mime-type<span class="o">=</span><span class="s2">"application/javascript; charset=utf-8"</span> <span class="se">\</span>
--add-header <span class="s2">"Cache-Control: max-age 86400"</span> --exclude <span class="s1">'*'</span> --include <span class="s1">'*.js'</span> <span class="o">&&</span> <span class="se">\</span>
s3cmd sync <span class="k">$(</span>S3_PUBLICATION_DIR<span class="k">)</span>/ s3://<span class="k">$(</span>S3_BUCKET<span class="k">)</span> --acl-public --add-header <span class="se">\</span>
<span class="s2">"Content-Encoding:gzip"</span> --mime-type<span class="o">=</span><span class="s2">"text/css; charset=utf-8"</span> --add-header <span class="se">\</span>
<span class="s2">"Cache-Control: max-age 86400"</span> --exclude <span class="s1">'*'</span> --include <span class="s1">'*.css'</span> <span class="o">&&</span> <span class="se">\</span>
s3cmd sync <span class="k">$(</span>S3_PUBLICATION_DIR<span class="k">)</span>/ s3://<span class="k">$(</span>S3_BUCKET<span class="k">)</span> --acl-public --add-header <span class="se">\</span>
<span class="s2">"Content-Encoding:gzip"</span> --mime-type<span class="o">=</span><span class="s2">"text/html; charset=utf-8"</span> --exclude <span class="s1">'*'</span> <span class="se">\</span>
--include <span class="s1">'*.html'</span> <span class="o">&&</span> <span class="se">\</span>
s3cmd sync <span class="k">$(</span>S3_PUBLICATION_DIR<span class="k">)</span>/ s3://<span class="k">$(</span>S3_BUCKET<span class="k">)</span> --acl-public --add-header <span class="se">\</span>
<span class="s2">"Content-Encoding:gzip"</span> --mime-type<span class="o">=</span><span class="s2">"application/xml; charset=utf-8"</span> --exclude <span class="se">\</span>
<span class="s1">'*'</span> --include <span class="s1">'*.xml'</span> <span class="o">&&</span> <span class="se">\</span>
s3cmd sync <span class="k">$(</span>S3_PUBLICATION_DIR<span class="k">)</span>/static/ s3://<span class="k">$(</span>S3_BUCKET<span class="k">)</span>/static/ --acl-public <span class="se">\</span>
--add-header <span class="s2">"Cache-Control: max-age 86400"</span> <span class="o">&&</span> <span class="se">\</span>
s3cmd sync <span class="k">$(</span>S3_PUBLICATION_DIR<span class="k">)</span>/theme/ s3://<span class="k">$(</span>S3_BUCKET<span class="k">)</span>/theme/ --acl-public <span class="se">\</span>
--add-header <span class="s2">"Cache-Control: max-age 86400"</span> <span class="o">&&</span> <span class="se">\</span>
s3cmd sync <span class="k">$(</span>S3_PUBLICATION_DIR<span class="k">)</span>/ s3://<span class="k">$(</span>S3_BUCKET<span class="k">)</span> --acl-public --delete-removed
</pre></div>
<p>While publish target just compiles website and put resulting content to $(OUTPUT) directory, compress target gzips
changed files putting them to $(S3_PUBLICATION_DIR) and s3_gzip_upload synchronizes local directory with S3 bucket
setting some useful headers.</p>
<p>Let's talk about compression firstly. It's done by separate self-written Python script that you can find and load in
<a target="_blank" href="https://gist.github.com/sukharevd/6202222">my aws-s3-gzip-compression.py GitHub Gist</a>.
It does exactly what I described as my suggestion - automated synchronization of only changed files. Not all files,
but only ones that can be compressed with good rate. Script compresses HTML, JavaScript, CSS and XML files. You can
use Makefile snippet as usage example for this script.</p>
<p>Now about synchronization with S3 bucket. There's a tool <code>s3cmd</code> that can be installed easily. As mentioned previously
it can synchronize local directory with S3 bucket using MD5 hash function. Important part about compression is
<code>Content-Encoding:gzip</code> HTTP header, it tells browser that it should decompress page before rendering. With include
and exclude attributes I specified that only HTML, JavaScript, CSS and XML files should have this header. As far as
it's publicly available website, acl-public attributes specifies that objects can be requested anonymously. </p>
<p>Defining character set in HTTP header helps browser to render pages faster. It's even recommended to avoid its
specification in meta tag inside webpages. Another rendering acceleration approach is to add <code>Cache-Control</code> header.
It tells browser that once loaded this HTTP resource (S3 object) will be cached by browser and any access to it
withing <code>max-age</code> would cause loading page from local cache, not from server. It's amazing approach if you have huge
CSS and JavaScript files.</p>Fix Skype's crashes while answering calls in Linux2013-08-29T09:28:00+03:00Dmitriy Sukharevtag:sukharevd.net,2013-08-29:fix-skypes-crashes-while-answering-calls-in-linux.html<p>Skype crashes when you answer a call in Debian-like Linux operating system? But you can initiate call without crashes
at the same time? Install package libasound2-plugins if so</p>
<div class="highlight"><pre><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">libasound2</span><span class="o">-</span><span class="n">plugins</span><span class="o">:</span><span class="n">i386</span>
</pre></div>
<p>Don't ask why it couldn't be installed as dependency. And why it causes such a strange behaviour. Frankly, I don't know.
But this solution works fine for me. Hope it will help you too.</p>
<p>Source: <a href="http://community.skype.com/t5/Linux/Skype-always-crashes-when-I-answer-a-call/td-p/1712890">Skype always crashes when I answer a call - Skype Community</a></p>New Wildfly 8 installation in couple minutes2013-08-08T20:56:00+03:00Dmitriy Sukharevtag:sukharevd.net,2013-08-08:wildfly-8-installation.html<p>In the <a target="_blank" href="http://sukharevd.net/jboss-as-7-configuration.html">previous article</a> I wrote how
to install JBoss AS 7 as service in Linux. In this one I'll enable you to install the new 8th version.</p>
<p>It got a new name. JBoss AS was renamed to Wildfly. The final version released recently, so it's a right time to try it.</p>
<h2>Preconditions</h2>
<ol>
<li><a target="_blank" href="http://sukharevd.net/install-oracle-jdk-under-linux.html">JDK 8 is installed</a> or <a target="_blank" href="http://sukharevd.net/install-oracle-jdk-7-in-3-simple-steps.html">JDK 7 is installed.</a></li>
</ol>
<h2>Installation</h2>
<p>The most part of installation steps for Wildfly 8 are the same <a target="_blank" href="http://sukharevd.net/jboss-as-7-configuration.html">as for JBoss AS 7</a>.
Therefore I will not duplicate them in this article.</p>
<p><em>UPD:</em> Since alpha4 Wildfly's developers supply init script for Debian-like distributions (not only for RHEL
distributions as before). I modified my install script to make it analyze environment and use relevant script.</p>
<p>For your convenience all installation steps were gathered into <a href="https://dl.dropboxusercontent.com/u/5339027/shared/dsps/wildfly-install.sh">
this script file</a> or <a href="https://gist.github.com/sukharevd/6087988">this GitHub Gist</a>.</p>
<p>It works for me in Debian Wheezy, Jessie, Ubuntu 12.04, 13.10, 14.04, and CentOS 6.4, but I don't think that for other Linux distributions
configuration will differ significantly.</p>
<p>To download and run this script just execute in the terminal the following commands</p>
<div class="highlight"><pre><span class="nb">cd</span> /tmp
wget https://dl.dropboxusercontent.com/u/5339027/shared/dsps/wildfly-install.sh -O wildfly-install.sh
sudo bash wildfly-install.sh
</pre></div>
<p>and Wildfly will be installed and run as service.</p>
<h2>Post-install</h2>
<p>After installation standard Wildfly welcome page is available at <a target="_blank" href="http://localhost:28080">http://localhost:28080</a>.</p>
<p>If you want to make the service be automatically started every time when your system starts up and your system is
Debian or RHEL-based, then run one of these two lines in terminal according to your distribution</p>
<div class="highlight"><pre>sudo update-rc.d wildfly defaults <span class="c"># for Debian-like distribution</span>
sudo chkconfig wildfly on --level 35 <span class="c"># for RHEL-like distribution</span>
</pre></div>
<p>otherwise you will be able to start it manually any time you need it</p>
<div class="highlight"><pre>sudo service wildfly start
</pre></div>Using JNI for calculations2013-07-29T09:59:00+03:00Dmitriy Sukharevtag:sukharevd.net,2013-07-29:using-jni-for-calculations.html<p>I had plenty free time lately. Out of boredom, I decided to try something new and interesting, something
what I wouldn't probably use for my job. Something like JNI.</p>
<p>JNI enables programmers to run native code from Java and vice versa. It can be used to
improve performance of calculations and to manipulate hardware directly that sometimes is impossible
with Java (for instance direct work graphical adapter).</p>
<p>I always wondered how to connect Java with code written in
other languages to improve performance. So I decided to write very simple JNI-based program for multiplying
matrices and make own benchmarks comparing JNI and pure Java performance.</p>
<p>First of all it's necessary to write Java class that has native methods. In our case it's MatrixMultiplier.
You can find this class as well as the whole example project at
<a target="_blank" href="https://github.com/sukharevd/jni-example" title="Example project's GitHub repository">this GitHub repository</a>.</p>
<p>Let's start with declaring native method. Technically it can't have body, because it's usually implemented in
different language in different file. Although in GWT it's possible to insert JavaScript code inside specially
formated comments, but this trick only possible because Google provides its own compiler for GWT.
I'm going to implement native method in C, so there's no body in Java code.</p>
<div class="highlight"><pre><span class="kd">private</span> <span class="kd">native</span> <span class="kt">int</span><span class="o">[][]</span> <span class="nf">multiply</span><span class="o">(</span><span class="kt">int</span><span class="o">[][]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">int</span><span class="o">[][]</span> <span class="n">b</span><span class="o">);</span>
</pre></div>
<p><code>pureJavaMultiply</code> method does the same, but in the pure Java.</p>
<div class="highlight"><pre><span class="kd">private</span> <span class="kt">int</span><span class="o">[][]</span> <span class="nf">pureJavaMultiply</span><span class="o">(</span><span class="kt">int</span><span class="o">[][]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">int</span><span class="o">[][]</span> <span class="n">b</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">int</span><span class="o">[][]</span> <span class="n">res</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="o">[</span><span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">][</span><span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">];</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">j</span> <span class="o"><</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">j</span><span class="o">++)</span> <span class="o">{</span>
<span class="n">res</span><span class="o">[</span><span class="n">i</span><span class="o">][</span><span class="n">j</span><span class="o">]</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">k</span> <span class="o"><</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">k</span><span class="o">++)</span> <span class="o">{</span>
<span class="n">res</span><span class="o">[</span><span class="n">i</span><span class="o">][</span><span class="n">j</span><span class="o">]</span> <span class="o">+=</span> <span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">][</span><span class="n">k</span><span class="o">]</span> <span class="o">*</span> <span class="n">b</span><span class="o">[</span><span class="n">k</span><span class="o">][</span><span class="n">j</span><span class="o">];</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="k">return</span> <span class="n">res</span><span class="o">;</span>
<span class="o">}</span>
</pre></div>
<p>To launch native method it's necessary to load shared library from the file.
For this purpose <code>System.load</code> method is used. In case of Windows replace <code>.so</code> with <code>.dll</code>.</p>
<div class="highlight"><pre><span class="n">File</span> <span class="n">sharedLibrary</span> <span class="o">=</span> <span class="k">new</span> <span class="n">File</span><span class="o">(</span><span class="s">"net_sukharevd_jni_example_MatrixMultiplier.so"</span><span class="o">);</span>
<span class="n">System</span><span class="o">.</span><span class="na">load</span><span class="o">(</span><span class="n">sharedLibrary</span><span class="o">.</span><span class="na">getAbsolutePath</span><span class="o">());</span>
</pre></div>
<p>Rest part of MatrixMultiplier class is dedicated to performance estimation of two multiplying methods.</p>
<p>It's necessary to compile this Java class</p>
<div class="highlight"><pre>javac src/net/sukharevd/jni/example/MatrixMultiplier.java
</pre></div>
<p>and generate C header file from it with usage of javah</p>
<div class="highlight"><pre>javah -d src/ -cp src/ net.sukharevd.jni.example.MatrixMultiplier
</pre></div>
<p>As result there will be a new header file in src folder that introduces <code>multiply</code> method</p>
<div class="highlight"><pre><span class="cm">/* DO NOT EDIT THIS FILE - it is machine generated */</span>
<span class="cp">#include <jni.h></span>
<span class="cm">/* Header for class net_sukharevd_jni_example_MatrixMultiplier */</span>
<span class="cp">#ifndef _Included_net_sukharevd_jni_example_MatrixMultiplier</span>
<span class="cp">#define _Included_net_sukharevd_jni_example_MatrixMultiplier</span>
<span class="cp">#ifdef __cplusplus</span>
<span class="k">extern</span> <span class="s">"C"</span> <span class="p">{</span>
<span class="cp">#endif</span>
<span class="cm">/*</span>
<span class="cm"> * Class: net_sukharevd_jni_example_MatrixMultiplier</span>
<span class="cm"> * Method: multiply</span>
<span class="cm"> * Signature: ([[I[[I)[[I</span>
<span class="cm"> */</span>
<span class="n">JNIEXPORT</span> <span class="n">jobjectArray</span> <span class="n">JNICALL</span> <span class="n">Java_net_sukharevd_jni_example_MatrixMultiplier_multiply</span>
<span class="p">(</span><span class="n">JNIEnv</span> <span class="o">*</span><span class="p">,</span> <span class="n">jobject</span><span class="p">,</span> <span class="n">jobjectArray</span><span class="p">,</span> <span class="n">jobjectArray</span><span class="p">);</span>
<span class="cp">#ifdef __cplusplus</span>
<span class="p">}</span>
<span class="cp">#endif</span>
<span class="cp">#endif</span>
</pre></div>
<p>The next step is to write implementation for this header file with the same
name, but with ".c" extension. Hope comments will help to understand this code.</p>
<div class="highlight"><pre><span class="cp">#include <stdlib.h></span>
<span class="cp">#include <jni.h></span>
<span class="cp">#include "net_sukharevd_jni_example_MatrixMultiplier.h"</span>
<span class="c1">// Multiplies matrix A to matrix B.</span>
<span class="n">JNIEXPORT</span> <span class="n">jobjectArray</span> <span class="n">JNICALL</span> <span class="nf">Java_net_sukharevd_jni_example_MatrixMultiplier_multiply</span>
<span class="p">(</span><span class="n">JNIEnv</span><span class="o">*</span> <span class="n">env</span><span class="p">,</span> <span class="n">jobject</span> <span class="n">obj</span><span class="p">,</span> <span class="n">jobjectArray</span> <span class="n">a</span><span class="p">,</span> <span class="n">jobjectArray</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
<span class="n">jint</span> <span class="n">size</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">GetArrayLength</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">a</span><span class="p">);</span>
<span class="c1">// READ MATRIX B (JVM object) TO BUFFER (native C array)</span>
<span class="kt">int</span> <span class="n">k</span><span class="p">;</span>
<span class="n">jintArray</span><span class="o">*</span> <span class="n">b_sub</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">size</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">jintArray</span><span class="o">*</span><span class="p">));</span> <span class="c1">// Subarray objects of B,</span>
<span class="c1">// stored for cleaning up.</span>
<span class="n">jint</span><span class="o">**</span> <span class="n">buf_b</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">size</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">jint</span><span class="o">*</span><span class="p">));</span> <span class="c1">// Buffer for matrix B.</span>
<span class="k">for</span> <span class="p">(</span><span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">b_sub</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">GetObjectArrayElement</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span> <span class="c1">// Fetch subarray of B.</span>
<span class="n">buf_b</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">GetIntArrayElements</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">b_sub</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">);</span> <span class="c1">// Read subarray to buffer.</span>
<span class="p">}</span>
<span class="c1">// CREATE RESULT ARRAY</span>
<span class="n">jclass</span> <span class="n">intArrCls</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">FindClass</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="s">"[I"</span><span class="p">);</span> <span class="c1">// Find int[] class.</span>
<span class="k">if</span> <span class="p">(</span><span class="n">intArrCls</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> <span class="cm">/* exception thrown */</span>
<span class="n">jobjectArray</span> <span class="n">result</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">NewObjectArray</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">intArrCls</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="c1">// Create array of int[].</span>
<span class="k">if</span> <span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> <span class="cm">/* out of memory error thrown */</span>
<span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">DeleteLocalRef</span><span class="p">(</span> <span class="n">env</span><span class="p">,</span> <span class="n">intArrCls</span> <span class="p">);</span> <span class="c1">// Delete reference to int[] class.</span>
<span class="c1">// MULTIPLY MATRICES</span>
<span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span>
<span class="n">jint</span><span class="o">*</span> <span class="n">buf_res_row</span> <span class="o">=</span> <span class="p">(</span><span class="n">jint</span><span class="o">*</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="n">size</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">jint</span><span class="p">));</span> <span class="c1">// Buffer for final matrix.</span>
<span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// READ I-TH ROW FROM A TO BUFFER</span>
<span class="n">jintArray</span> <span class="n">a_i</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">GetObjectArrayElement</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
<span class="n">jint</span><span class="o">*</span> <span class="n">buf_a_i</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">GetIntArrayElements</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">a_i</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="c1">// CALCULATE I-TH ROW OF RESULT</span>
<span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">buf_res_row</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">buf_res_row</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+=</span> <span class="n">buf_a_i</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="n">buf_b</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">j</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">ReleaseIntArrayElements</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">a_i</span><span class="p">,</span> <span class="n">buf_a_i</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">DeleteLocalRef</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">a_i</span><span class="p">);</span>
<span class="c1">// COPY I-TH ROW TO RESULT OBJECT</span>
<span class="n">jintArray</span> <span class="n">res_row</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">NewIntArray</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">res_row</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> <span class="cm">/* out of memory error thrown */</span>
<span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">SetIntArrayRegion</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">res_row</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">buf_res_row</span><span class="p">);</span> <span class="c1">// Firstly copy to new</span>
<span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">SetObjectArrayElement</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">result</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">res_row</span><span class="p">);</span> <span class="c1">// array object, and</span>
<span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">DeleteLocalRef</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">res_row</span><span class="p">);</span> <span class="c1">// then to matrix.</span>
<span class="p">}</span>
<span class="c1">// CLEAN UP</span>
<span class="n">free</span><span class="p">(</span><span class="n">buf_res_row</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">ReleaseIntArrayElements</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">b_sub</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">buf_b</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">DeleteLocalRef</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">b_sub</span><span class="p">[</span><span class="n">k</span><span class="p">]);</span>
<span class="p">}</span>
<span class="n">free</span><span class="p">(</span><span class="n">buf_b</span><span class="p">);</span>
<span class="n">free</span><span class="p">(</span><span class="n">b_sub</span><span class="p">);</span>
<span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>When implementation is ready, it's possible to compile it obtaining <code>.so</code> shared library file.
For <strong>Linux</strong> it could be done executing command</p>
<div class="highlight"><pre>gcc -O3 -fPIC -shared -I /usr/lib/jvm/java-7-oracle/include/ <span class="se">\</span>
-I /usr/lib/jvm/java-7-oracle/include/linux/ <span class="se">\</span>
-o net_sukharevd_jni_example_MatrixMultiplier.so <span class="se">\</span>
src/net_sukharevd_jni_example_MatrixMultiplier.c
</pre></div>
<ul>
<li><em>-O3</em> means that it's desired to optimize compilation reducing code size and execution time.</li>
<li><em>-shared</em> means that the result should be a shared library.</li>
<li><em>-fPIC</em> (Position Independent Code) makes jumps be generated with relative rather than absolute addressing, that
<a target="_blank" href="http://stackoverflow.com/questions/5311515/gcc-fpic-option#comment5991614_5311538">makes sense for shared libraries</a>.</li>
<li><em>-I</em> tells compiler where to look for header files (e.g. jni.h)</li>
<li><em>-o</em> specifies where output file should be saved.</li>
</ul>
<p>To use gcc in <strong>Windows</strong> it's necessary to install it. For Windows gcc is supplied as part MinGW (or
<a target="_blank" href="http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.8.0/64-bit/threads-posix/seh/x64-4.8.0-release-posix-seh-rev2.7z/download">MinGW-w64</a>
for x64 systems).
It's also nice to have gcc in the PATH, so add MinGW's bin directory to PATH. As soon as you have
gcc, execute the following in command line (replacing path to JDK):</p>
<div class="highlight"><pre>gcc -O3 -shared^
-I <span class="s2">"C:\Program Files\Java\jdk1.7.0_25\include"</span>^
-I <span class="s2">"C:\Program Files\Java\jdk1.7.0_25\include\win32"</span>^
-o MatrixMultiplier.dll^
src<span class="se">\n</span>et_sukharevd_jni_example_MatrixMultiplier.c
</pre></div>
<p>Finally it's time to run the code</p>
<div class="highlight"><pre>java -cp src/ net.sukharevd.jni.example.MatrixMultiplier
</pre></div>
<p>The Java class makes benchmarks for different sizes of matrices (N). Results are represented in a table</p>
<table class="table">
<tr><th> N </th><th> tJni, [ms]</th><th>tPureJava, [ms]</th><th> Ratio </th></tr>
<tr><td> 250 </td><td> 16 </td><td> 28 </td><td> 1.75 </td></tr>
<tr><td> 500 </td><td> 257 </td><td> 480 </td><td> 1.87 </td></tr>
<tr><td> 750 </td><td> 1,288 </td><td> 1,801 </td><td> 1.40 </td></tr>
<tr><td> 1000 </td><td> 4,126 </td><td> 4,638 </td><td> 1.12 </td></tr>
<tr><td> 1250 </td><td> 9,513 </td><td> 13,040 </td><td> 1.37 </td></tr>
<tr><td> 1500 </td><td> 16,267 </td><td> 22,560 </td><td> 1.39 </td></tr>
<tr><td> 1750 </td><td> 26,781 </td><td> 40,954 </td><td> 1.53 </td></tr>
<tr><td> 2000 </td><td> 43,172 </td><td> 64,025 </td><td> 1.48 </td></tr>
<tr><td> 2250 </td><td> 62,540 </td><td> 89,050 </td><td> 1.42 </td></tr>
<tr><td> 2500 </td><td> 82,934 </td><td> 135,473 </td><td> 1.63 </td></tr>
<tr><td> 2750 </td><td> 113,912 </td><td> 180,310 </td><td> 1.58 </td></tr>
<tr><td> 3000 </td><td> 156,210 </td><td> 245,301 </td><td> 1.57 </td></tr>
<tr><td> 3250 </td><td> 201,585 </td><td> 300,490 </td><td> 1.49 </td></tr>
<tr><td> 3500 </td><td> 246,014 </td><td> 413,289 </td><td> 1.68 </td></tr>
<tr><td> 3750 </td><td> 308,626 </td><td> 460,653 </td><td> 1.49 </td></tr>
<tr><td> 4000 </td><td> 397,392 </td><td> 630,182 </td><td> 1.59 </td></tr>
</table>
<p>The table shows that implemented native method gave about 1.5 times boost which means that it
was worth to write all this C code for the sake of performance.</p>
<p>But it's not the first version of this method. Former one was much less
efficient. In fact the only difference between them is the way of fetching
subarrays from matrices. The former one didn't buffered the second matrix,
instead it obtained elements when they were required</p>
<div class="highlight"><pre><span class="c1">// CALCULATE I-TH ROW OF RESULT</span>
<span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">buf_res_row</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// !!! NOW B ISN'T BUFFERED ENTIRELY !!!</span>
<span class="n">jintArray</span> <span class="n">b_k</span> <span class="o">=</span> <span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">GetObjectArrayElement</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
<span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">GetIntArrayRegion</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">b_k</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">buf_b_k</span><span class="p">);</span>
<span class="p">(</span><span class="o">*</span><span class="n">env</span><span class="p">)</span><span class="o">-></span><span class="n">DeleteLocalRef</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">b_k</span><span class="p">);</span>
<span class="n">buf_res_row</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+=</span> <span class="n">buf_a_i</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="n">buf_b_k</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>Such a change caused serious performance problems shown in the table below</p>
<table class="table">
<tr><th> N </th><th> tJni, [ms]</th><th>tPureJava, [ms]</th><th> Ratio </th></tr>
<tr><td> 250 </td><td> 1199 </td><td> 30 </td><td> 42.82 </td></tr>
<tr><td> 500 </td><td> 10231 </td><td> 511 </td><td> 20.02 </td></tr>
<tr><td> 750 </td><td> 35587 </td><td> 1920 </td><td> 18.53 </td></tr>
<tr><td> 1000 </td><td> 85362 </td><td> 5158 </td><td> 16.55 </td></tr>
<tr><td> 1250 </td><td> 167264 </td><td> 12560 </td><td> 13.32 </td></tr>
<tr><td> 1500 </td><td> 293473 </td><td> 22748 </td><td> 12.90 </td></tr>
<tr><td> 1750 </td><td> 463501 </td><td> 39921 </td><td> 11.61 </td></tr>
<tr><td> 2000 </td><td> 694096 </td><td> 62484 </td><td> 11.11 </td></tr>
<tr><td> 2250 </td><td> 996630 </td><td> 91282 </td><td> 10.92 </td></tr>
<tr><td> 2500 </td><td> 1361381 </td><td> 120622 </td><td> 11.29 </td></tr>
<tr><td> 2750 </td><td> 1818452 </td><td> 189720 </td><td> 9.58 </td></tr>
<tr><td> 3000 </td><td> 2382053 </td><td> 240613 </td><td> 9.90 </td></tr>
</table>
<p>I couldn't imagine that this change would affect performance more than 10 times!
As mentioned in <a target="_blank" href="http://www.ibm.com/developerworks/library/j-jni/#notc">this IBM article</a>
looking up for objects in JVM could be very expensive. In the former edition this
looking up was done N times more than necessary. JVM objects should be
cached to avoid redundant and expensive looking up and work with them also
should be minimized. Not keeping these recommendation cost me tenfold drop in performance.</p>
<p>Using JNI could significantly improve performance of Java applications. But writing
JNI programs is much more sophisticated than writing pure Java implementations. Moreover
there are no guarantees of optimality for such solutions. Poor implementation could give
opposite results decreasing overall performance.</p>Install Oracle JDK 7 in 3 simple steps2013-07-01T15:56:00+03:00Dmitriy Sukharevtag:sukharevd.net,2013-07-01:install-oracle-jdk-7-in-3-simple-steps.html<p>This article shows how to install or update Oracle JDK 7 in semiautomatic way
under Linux operating systems, including Ubuntu, Debian and CentOS. Semi is
because Oracle has its proprietary license you have to accept before downloading.</p>
<ol>
<li>So the first step is to download JDK from
<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Oracle's site</a>.</li>
<li>Then download <a target="_blank" href="http://sukharevd.net/static/files/blog/oracle-jdk-7/oracle-jdk-7-update.sh">this bash script</a>
to the same directory where JDK is.</li>
<li>
<p>Run the script as sudoer:</p>
<div class="highlight"><pre>sudo bash oracle-jdk-7-update.sh
</pre></div>
</li>
</ol>
<p>If in the end of output you see something like</p>
<div class="highlight"><pre>java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)
</pre></div>
<p>then Oracle JDK 7 was successfully installed.
Congratulations!</p>
<!--
For curious here is the listing of that bash script.
:::bash
#!/bin/bash
# Usage: $ sudo bash oracle-jdk-7-update <JDK Update> <JDK Architecture>
UPDATE=$1
ARCH=$2
INSTALL_DIR=/usr/lib/jvm
JDK7_DIR=$INSTALL_DIR/java-7-oracle
echo "This script will install Oracle JDK 7 from tar.gz file."
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root."
exit 1
fi
echo "Extracting archive..."
tar -xzf jdk-7u$UPDATE-linux-$ARCH.tar.gz
if [ $? -ne 0 ]; then
echo "Error while extraction archive."
exit 1
fi
if [ ! -d jdk1.7.0_$UPDATE ]; then
echo "Unexpected archive content."
exit 1
fi
echo "Moving content to installation directory..."
[ ! -e $INSTALL_DIR ] && mkdir -p $INSTALL_DIR
[ -e $INSTALL_DIR/jdk1.7.0_$UPDATE ] && rm -r $INSTALL_DIR/jdk1.7.0_$UPDATE/
[ -e $JDK7_DIR ] && rm $JDK7_DIR
mv jdk1.7.0_$UPDATE/ $INSTALL_DIR
ln -s $INSTALL_DIR/jdk1.7.0_$UPDATE/ $JDK7_DIR
echo "Updating alternatives..."
# The following part has been taken from script
# http://webupd8.googlecode.com/files/update-java-0.5b
# and modified to make it work without X-server.
gzip -9 $JDK7_DIR/man/man1/*.1 >/dev/null 2>&1 &
LATEST=$((`update-alternatives --query java|grep Priority:|awk '{print $2}'|sort -n|tail -1`+1));
if [ -d "$JDK7_DIR/man/man1" ];then
for f in $JDK7_DIR/man/man1/*; do
name=`basename $f .1.gz`;
#some files, like jvisualvm might not be links. Further assume this for corresponding man page
if [ ! -f "/usr/bin/$name" -o -L "/usr/bin/$name" ]; then
if [ ! -f "$JDK7_DIR/man/man1/$name.1.gz" ]; then
name=`basename $f .1`; #handle any legacy uncompressed pages
fi
update-alternatives --install /usr/bin/$name $name $JDK7_DIR/bin/$name $LATEST \
--slave /usr/share/man/man1/$name.1.gz $name.1.gz $JDK7_DIR/man/man1/$name.1.gz
fi
done
#File links without man pages
[ -f $JDK7_DIR/bin/java_vm ] && update-alternatives --install /usr/bin/java_vm \
java_vm $JDK7_DIR/jre/bin/java_vm $LATEST
[ -f $JDK7_DIR/bin/jcontrol ] && update-alternatives --install /usr/bin/jcontrol \
jcontrol $JDK7_DIR/bin/jcontrol $LATEST
else #no man pages available
for f in $JDK7_DIR/bin/*; do
name=`basename $f`;
#some files, like jvisualvm might not be links
if [ ! -f "/usr/bin/$name" -o -L "/usr/bin/$name" ]; then
update-alternatives --install /usr/bin/$name $name $JDK7_DIR/bin/$name $LATEST
fi
done
fi
echo "Setting up Mozilla plugin..."
#File links that apt-get misses
[ -f $JDK7_DIR/bin/libnpjp2.so ] && update-alternatives --install \
/usr/lib/mozilla/plugins/libnpjp2.so libnpjp2.so $JDK7_DIR/jre/lib/i386/libnpjp2.so $LATEST
echo "Setting up env. variable JAVA_HOME..."
cat > /etc/profile.d/java-home.sh << "EOF"
export JAVA_HOME="/usr/lib/jvm/java-7-oracle"
export PATH="$JAVA_HOME/bin:$PATH"
EOF
echo "Checking version..."
java -version
echo "Done."
-->Setting up Amazon S3 static website2013-06-08T21:20:00+03:00Dmitriy Sukharevtag:sukharevd.net,2013-06-08:setting-up-amazon-s3-static-website.html<p>I couldn't imagine that I would use this link so often. It's a magnificent
Amazon's tutorial that shows how to deploy static website to Amazon S3
in case of custom domain name. I'll cache it here ツ</p>
<p><a target="_blank" href="http://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html">Example: Setting Up a Static Website Using a Custom Domain</a></p>Generating routing rules for Amazon S3 bucket2013-06-08T20:10:00+03:00Dmitriy Sukharevtag:sukharevd.net,2013-06-08:generating-routing-rules-for-amazon-s3-bucket.html<p>Today I've moved my personal site from free PHP hosting to Amazon S3 in static website hosting mode.
The reason was that I didn't feel that it's right thing to host static content in MySQL database ツ.
As result all my URLs changed. Search engines indexed old URLs long time ago, and to save their
rates it was necessary to make redirection from old URLs to new ones. Yes, in some way it's a SEO-related article ツ</p>
<p>There were not too many pages, but enough to consider at least semi-automating the process. First I
created a list of old URLs. For this purpose in Linux I used wget on old website version:</p>
<div class="highlight"><pre>wget -r --spider http://sukharevd.kiev.ua --no-verbose
</pre></div>
<p>and cropped hostnames from its output using Geany (vertical text selection rules!), and less than in minute I had a list.</p>
<p>Then I had to put the corresponding item to each element in the list. Unfortunately I had no choise but do it manually.
So I had a file with two columns:</p>
<div class="highlight"><pre><span class="n">index</span><span class="p">.</span><span class="n">php</span> <span class="n">index</span><span class="p">.</span><span class="n">html</span>
<span class="n">blog</span><span class="p">.</span><span class="n">php</span><span class="o">?</span><span class="n">id</span><span class="o">=</span><span class="mi">21</span> <span class="n">blog</span><span class="o">/</span><span class="n">mysql</span><span class="o">-</span><span class="n">utf</span><span class="o">-</span><span class="mi">8</span><span class="o">-</span><span class="n">database</span><span class="o">-</span><span class="n">creation</span><span class="o">-</span><span class="n">snippet</span><span class="p">.</span><span class="n">html</span>
<span class="n">blog</span><span class="p">.</span><span class="n">php</span><span class="o">?</span><span class="n">id</span><span class="o">=</span><span class="mi">20</span> <span class="n">blog</span><span class="o">/</span><span class="n">jboss</span><span class="o">-</span><span class="n">as</span><span class="o">-</span><span class="mi">7</span><span class="o">-</span><span class="n">configuration</span><span class="p">.</span><span class="n">html</span>
<span class="p">...</span>
</pre></div>
<p>Amazon S3's routing rules are XML file actually. To convert my text file to XML format I decided to write
a simple Python script. Luckily, 'cause I didn't obtain correct URLs after the first attempt ツ</p>
<blockquote>
<p><strong>UPD:</strong> It's Ok if you don't know how to execute Python scripts. I wrote a <a target="_blank" href="http://sukharevd.net/static/files/blog/s3routes/index.html">simple GWT application</a> to simplify the
process, it replaces Python script completely. Just follow the link and copy-paste the redirection mapping you've just get (yes, that two columns). <br />
For curious, you can find the source code of this GWT application in <a target="_blank" href="https://github.com/sukharevd/s3routes">this GitHub repository</a>.</p>
</blockquote>
<div class="highlight"><pre><span class="c">#!/usr/bin/python</span>
<span class="kn">import</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">re</span>
<span class="k">def</span> <span class="nf">txt_to_xml</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
<span class="n">fr</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="n">fw</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span> <span class="o">+</span> <span class="s">'.xml'</span><span class="p">,</span> <span class="s">'w'</span><span class="p">)</span>
<span class="n">fw</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'<?xml version="1.0"?></span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="n">fw</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'<RoutingRules></span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">fr</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">line</span><span class="p">:</span>
<span class="n">fw</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">continue</span>
<span class="n">listFromLine</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">'\s+'</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
<span class="n">fw</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'<RoutingRule><Condition><KeyPrefixEquals></span><span class="si">%s</span><span class="s"></KeyPrefixEquals></Condition>'</span>
<span class="s">'<Redirect><ReplaceKeyWith></span><span class="si">%s</span><span class="s"></ReplaceKeyWith></Redirect></RoutingRule></span><span class="se">\n</span><span class="s">'</span>
<span class="o">%</span> <span class="p">(</span><span class="n">listFromLine</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">listFromLine</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="p">)</span>
<span class="n">fw</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'</RoutingRules>'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">filename</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">:</span>
<span class="n">txt_to_xml</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
</pre></div>
<p>After executing the script</p>
<div class="highlight"><pre>$ ./s3-routes-generator.py redirects.txt
</pre></div>
<p>I had XML file ready for insertion to AWS S3 bucket's settings via AWS Console:</p>
<div style="text-align:center">
<img alt="S3 bucket's settings" src="http://sukharevd.net/static/files/blog/s3-redirection/s3-redirection.png" />
</div>
<p>and after applying changes the requests to old URLs are redirected:</p>
<div style="text-align:center">
<img alt="Redirection in browser" src="http://sukharevd.net/static/files/blog/s3-redirection/s3-redirection-prove.png" />
</div>
<p>Well, I've got acquainted with SEO. Hope, I will have much time posting here in future, and creating
interesting and searchable content.</p>MySQL. UTF-8 database creation snippet2013-01-07T01:06:00+02:00Dmitriy Sukharevtag:sukharevd.net,2013-01-07:mysql-utf-8-database-creation-snippet.html<p>Well, I haven't remembered syntax of database creation in UTF-8 character set
with MySQL for quite a long time. Finally I decided to write a little snippet
because I used it so often last time.</p>
<div class="highlight"><pre><span class="k">CREATE</span> <span class="k">DATABASE</span> <span class="k">database</span> <span class="nb">CHARACTER</span> <span class="k">SET</span> <span class="n">utf8</span> <span class="k">COLLATE</span> <span class="n">utf8_general_ci</span><span class="p">;</span>
<span class="k">CREATE</span> <span class="k">USER</span> <span class="s1">'username'</span><span class="o">@</span><span class="s1">'localhost'</span> <span class="n">IDENTIFIED</span> <span class="k">BY</span> <span class="s1">'password'</span><span class="p">;</span>
<span class="k">GRANT</span> <span class="k">ALL</span> <span class="k">PRIVILEGES</span> <span class="k">ON</span> <span class="k">database</span><span class="p">.</span><span class="o">*</span> <span class="k">TO</span> <span class="s1">'username'</span><span class="o">@</span><span class="s1">'localhost'</span><span class="p">;</span>
</pre></div>JBoss AS 7 Configuration2013-01-06T19:16:23+02:00Dmitriy Sukharevtag:sukharevd.net,2013-01-06:jboss-as-7-configuration.html<p>It's kind of not trivial to use JBoss AS after usage of containers like Apache Tomcat or Jetty.
And unfortunately JBoss AS isn't distributed in the way that let it be easily set up as service.
This article is just a remember for me how should I install and configure JBoss AS 7.</p>
<p>I'm using Debian Wheezy, but I don't think that for other Linux distributions configuration will differ significantly.</p>
<h2>Preconditions</h2>
<ol>
<li>JDK is installed.</li>
<li>JAVA_HOME environment variable is set.</li>
</ol>
<p><br /> </p>
<blockquote>
<p>For your convenience all following steps were gathered to <a href='https://dl.dropbox.com/u/5339027/shared/dsps/jboss-install.tar.gz'>the script file</a>.</p>
</blockquote>
<h2>Installation</h2>
<ol>
<li>
<p>Download JBoss AS 7.</p>
<pre>wget http://download.jboss.org/jbossas/7.1/jboss-as-7.1.1.Final/jboss-as-7.1.1.Final.tar.gz</pre>
</li>
<li>
<p>Untar the archive.</p>
<pre>tar -xvzf jboss-as-7.1.1.Final.tar.gz -C /opt</pre>
</li>
<li>
<p>Make a link for easier upgrade of JBoss AS.</p>
<pre>ln -s /opt/jboss-as-7.1.1 /opt/jboss-as</pre>
</li>
<li>
<p>Create user.</p>
<pre>useradd -s /sbin/nologin jboss-as</pre>
</li>
<li>
<p>Change owner for jboss-as's directory.</p>
<pre>chown -R jboss-as:jboss-as /opt/jboss-as</pre>
<pre>chown -R jboss-as:jboss-as /opt/jboss-as/</pre>
</li>
<li>
<p>Delete downloaded archive</p>
<pre>rm jboss-as-7.1.1.Final.tar.gz</pre>
</li>
<li>
<p>Initialize JBoss AS as service.</p>
<pre>vim /etc/init.d/jboss-as</pre>
<pre>#!/bin/sh
### BEGIN INIT INFO
# Provides: jboss-as
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/Stop JBoss AS 7
### END INIT INFO
JBOSS_USER=jboss-as
JBOSS_DIR=/opt/jboss-as
case "$1" in
start)
echo "Starting JBoss AS 7..."
start-stop-daemon --start --quiet --background --chuid $JBOSS_USER --exec $JBOSS_DIR/bin/standalone.sh
;;
stop)
echo "Stopping JBoss AS 7..."
start-stop-daemon --start --quiet --background --chuid $JBOSS_USER --exec $JBOSS_DIR/bin/jboss-cli.sh -- --connect command=:shutdown
;;
log)
echo "Showing server.log..."
tail -500f $JBOSS_DIR/standalone/log/server.log
;;
*)
echo "Usage: /etc/init.d/jboss-as {start|stop}"
exit 1
;;
esac
exit 0</pre>
<pre>chmod 755 /etc/init.d/jboss-as</pre>
</li>
</ol>
<h2>Configuration</h2>
<ol>
<li>
<p>The default timeout is too low for most of my applications, therefore I override it.</p>
<pre>sed -i -e 's, \
<deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000"/>, \
<deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" deployment-timeout="240"/>,g' \
/opt/jboss-as/standalone/configuration/standalone.xml</pre>
</li>
<li>
<p>I wanna be able to redefine root context, therefore I disable default one.</p>
<pre>sed -i -e 's, \
<virtual-server name="default-host" enable-welcome-root="true">, \
<virtual-server name="default-host" enable-welcome-root="false">,g' \
/opt/jboss-as/standalone/configuration/standalone.xml</pre>
</li>
<li>
<p>I need port to be listened by all network interfaces therefore I change the way it's set.</p>
<pre>sed -i -e 's, \
<inet-address value="${jboss.bind.address:127.0.0.1}"/>, \
<any-address/>,g' \
/opt/jboss-as/standalone/configuration/standalone.xml</pre>
<p>Alternatively I could define jboss.bind.address VM parameter. Say in this way</p>
<pre>echo 'export JAVA_OPTS="$JAVA_OPTS -Djboss.bind.address=192.168.0.1"' >> /opt/profile.d/java.sh</pre>
</li>
<li>
<p>Often some application already use port 8080, therefore I prefere change ports that JBoss AS listens to.</p>
<pre>sed -i -e 's, \
<socket-binding name="ajp" port="8009"/>, \
<socket-binding name="ajp" port="28009"/>,g' \
jboss-as/standalone/configuration/standalone.xml</pre>
<pre>sed -i -e 's, \
<socket-binding name="http" port="8080"/>, \
<socket-binding name="http" port="28080"/>,g' \
jboss-as/standalone/configuration/standalone.xml</pre>
<pre>sed -i -e 's, \
<socket-binding name="https" port="8443"/>, \
<socket-binding name="https" port="28443"/>,g' \
jboss-as/standalone/configuration/standalone.xml</pre>
<pre>sed -i -e 's, \
<socket-binding name="osgi-http" interface="management" port="8090"/>, \
<socket-binding name="osgi-http" interface="management" port="28090"/>,g' \
jboss-as/standalone/configuration/standalone.xml</pre>
</li>
</ol>
<p><b>Note:</b> It would be better to avoid backslashes and line wrapping in sed expressions. I used them only for markup reasons.</p>
<p>You can find bash script for installation and configuration JBoss AS 7 <a href='https://dl.dropbox.com/u/5339027/shared/dsps/jboss-install.tar.gz'>here</a>.</p>SSH tunneling in Linux2013-01-06T14:17:29+02:00Dmitriy Sukharevtag:sukharevd.net,2013-01-06:ssh-tunneling-in-linux.html<p>Once you have SSH access to the server, you can use tunneling to connect to
its services that are unavailable to others.</p>
<p>Use the following command to make example.com:1521 be available as your
localhost:1522.</p>
<div class="highlight"><pre>ssh -N -p 22 usename@example.com -L 1521:localhost:1522
</pre></div>Code highlighting in Vim2012-08-25T21:38:00+03:00Dmitriy Sukharevtag:sukharevd.net,2012-08-25:code-highlighting-in-vim.html<p>To enable code highlighting in Vim add text "syntax on" to file ~/.vimrc or execute the following command:</p>
<div class="highlight"><pre><span class="nb">echo</span> <span class="s2">"syntax on"</span> >> ~/.vimrc
</pre></div>
<p>If you want to enable highlighting only once, you can execute the following command from Vim (press Esc before typing to exit from insert/replace mode):</p>
<div class="highlight"><pre>:syntax on
</pre></div>Gnome 3. Disabling suspend when the lid is closed2012-08-24T21:51:44+03:00Dmitriy Sukharevtag:sukharevd.net,2012-08-24:gnome-3-disabling-suspend-when-the-lid-is-closed.html<p>For some reason there's no way to change standard behaviour when the lid is
closed in Gnome3 via System Settings. Fortunately it's possible to do in
terminal. For this execute the following commands (NOT as root):</p>
<div class="highlight"><pre><span class="nv">$ </span>gsettings <span class="nb">set </span>org.gnome.settings-daemon.plugins.power lid-close-ac-action <span class="s2">"<action>"</span>
<span class="nv">$ </span>gsettings <span class="nb">set </span>org.gnome.settings-daemon.plugins.power lid-close-battery-action <span class="s2">"<action>"</span>
</pre></div>
<p>where <action> should be one from the list: <code>nothing|blank|suspend|hibernate|shutdown</code></p>Rapid logger creation in Eclipse2012-04-07T00:35:17+03:00Dmitriy Sukharevtag:sukharevd.net,2012-04-07:rapid-logger-creation-in-eclipse.html<p>In Eclipse it's possible to create easy to insert templates. Probably you
have used "main" template by typing "main" and pressing Ctrl + Space to create
main method. You also probably have faced the problem of logging huge amount
of classes, and everywhere you needed to use logger factory, type current
class name and choose imports you want to add (that is very tadioous in my
opinion).</p>
<p>Here I'll show you how to add Eclipse template for rapid creation of slf4j
loggers in your classes.</p>
<p>You need to do the following two steps for this purpose:</p>
<ol>
<li>Open Window -> Preferences -> Java -> Editor -> Templates -> New...</li>
<li>Type any name you want to associate with creation of slf4j logger (say, "logger"). You will type this name and press Ctrl+Space to create logger instance.</li>
<li>
<p>Insert the following snippet to pattern text area:</p>
<div class="highlight"><pre><span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">Logger</span> <span class="n">LOGGER</span> <span class="o">=</span> <span class="n">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="n">$</span><span class="o">{</span><span class="n">enclosing_type</span><span class="o">}.</span><span class="na">class</span><span class="o">);</span>
<span class="n">$</span><span class="o">{:</span><span class="n">import</span><span class="o">(</span><span class="n">org</span><span class="o">.</span><span class="na">slf4j</span><span class="o">.</span><span class="na">Logger</span><span class="o">,</span> <span class="n">org</span><span class="o">.</span><span class="na">slf4j</span><span class="o">.</span><span class="na">LoggerFactory</span><span class="o">)}</span>
</pre></div>
</li>
</ol>
<p>That's it. Save changes and enjoy logging.</p>Configuring warnings in Eclipse2012-03-31T12:39:27+03:00Dmitriy Sukharevtag:sukharevd.net,2012-03-31:configurating-warnings-in-eclipse.html<p>It's possible to tell Eclipse which code should lead to warning, which to error and which should be handled as normal.</p>
<p>You need to do the following two steps for this purpose:</p>
<ol>
<li>Open Window -> Preferences -> Java -> Compiler -> Errors/Warnings.</li>
<li>Change properties in the way you want.</li>
</ol>
<p>My settings are shown below.</p>
<div style="text-align:center">
<a href="http://sukharevd.net/static/files/blog/eclipse_warn/01-code-style.png" rel="lightbox[id15]" title="Code Style"><img class="link" src="http://sukharevd.net/static/files/blog/eclipse_warn/01-code-style-50.png" alt="01-code-style" /></a>
<br />
<a href="http://sukharevd.net/static/files/blog/eclipse_warn/02-programming-problems.png" rel="lightbox[id15]" title="Potential Programming Problems"><img class="link" src="http://sukharevd.net/static/files/blog/eclipse_warn/02-programming-problems-50.png" alt="02-programming-problems" /></a>
<br />
<a href="http://sukharevd.net/static/files/blog/eclipse_warn/03-name-conflicts.png" rel="lightbox[id15]" title="Name Shadowing and Conflicts"><img class="link" src="http://sukharevd.net/static/files/blog/eclipse_warn/03-name-conflicts-50.png" alt="03-name-conflicts" /></a>
<br />
<a href="http://sukharevd.net/static/files/blog/eclipse_warn/04-deprecated-api.png" rel="lightbox[id15]" title="Deprecated API"><img class="link" src="http://sukharevd.net/static/files/blog/eclipse_warn/04-deprecated-api-50.png" alt="04-deprecated-api" /></a>
<br />
<a href="http://sukharevd.net/static/files/blog/eclipse_warn/05-unnecessary-code.png" rel="lightbox[id15]" title="Unnecessary Code"><img class="link" src="http://sukharevd.net/static/files/blog/eclipse_warn/05-unnecessary-code-50.png" alt="05-unnecessary-code" /></a>
<br />
<a href="http://sukharevd.net/static/files/blog/eclipse_warn/06-generic-types.png" rel="lightbox[id15]" title="Generic Types"><img class="link" src="http://sukharevd.net/static/files/blog/eclipse_warn/06-generic-types-50.png" alt="06-generic-types" /></a>
<br />
<a href="http://sukharevd.net/static/files/blog/eclipse_warn/07-annotations.png" rel="lightbox[id15]" title="Annotations"><img class="link" src="http://sukharevd.net/static/files/blog/eclipse_warn/07-annotations-50.png" alt="07-annotations" /></a>
</div>Windows 7. Opening up ports for servers2012-03-31T12:23:59+03:00Dmitriy Sukharevtag:sukharevd.net,2012-03-31:windows-7-opening-up-ports-for-servers.html<p>Very handful answer at superuser.com:<br />
<a target="_blank" href="http://superuser.com/questions/92488/apache-server-on-windows-7-opening-up-ports/92494#92494">Apache Server on Windows 7 opening up ports?</a></p>Bugzilla: error which isn't error2011-06-24T09:53:57+03:00Dmitriy Sukharevtag:sukharevd.net,2011-06-24:bugzilla-error-which-isnt-error.html<blockquote>
<p>The local XML file './data/bugzilla-update.xml' cannot be created. Please
make sure the web server can write in this directory and that you can access
the web. If you are behind a proxy, set the proxy_url parameter correctly.</p>
</blockquote>
<p>If you got this error and you are sure that the user who started the web-server
can create files in data/ folder, then just check if Bugzilla's update server
is up. For doing this go <a href="http://validator.w3.org/">here</a> and check
address <code>http://updates.bugzilla.org</code>. If you get <code>500 read
timeout</code> or some other error, then obviously it's not your fault and you
simply need to wait several hours, otherwise keep googling.</p>Performance Overview of String Concatenation2011-04-13T23:54:24+03:00Dmitriy Sukharevtag:sukharevd.net,2011-04-13:performance-overview-of-string-concatenation.html<p>Today I decided to test different ways of concatenation. I chose concatenation with "+" operator, String.format(...) and StringBuilder. I wrote simple code for determining time in milliseconds for each test.</p>
<p><b>Source Code:</b></p>
<div class="highlight"><pre><span class="kn">package</span> <span class="n">test</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Iterator</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.TreeSet</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kt">double</span> <span class="n">A</span> <span class="o">=</span> <span class="mi">300</span><span class="n">d</span><span class="o">;</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kt">long</span> <span class="n">B</span> <span class="o">=</span> <span class="mi">80087L</span><span class="o">;</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kt">int</span> <span class="n">C</span> <span class="o">=</span> <span class="mi">7897</span><span class="o">;</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kt">char</span> <span class="n">D</span> <span class="o">=</span> <span class="sc">'5'</span><span class="o">;</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kt">boolean</span> <span class="n">E</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">F</span> <span class="o">=</span> <span class="s">"Text Text Text"</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">InterruptedException</span> <span class="o">{</span>
<span class="c1">// Warming up begin</span>
<span class="n">Thread</span><span class="o">.</span><span class="na">sleep</span><span class="o">(</span><span class="mi">10000</span><span class="o">);</span>
<span class="n">test1</span><span class="o">();</span>
<span class="n">test2</span><span class="o">();</span>
<span class="n">test3</span><span class="o">();</span>
<span class="c1">// Warming up end</span>
<span class="kt">long</span> <span class="n">test1</span> <span class="o">=</span> <span class="n">test1</span><span class="o">();</span>
<span class="kt">long</span> <span class="n">test2</span> <span class="o">=</span> <span class="n">test2</span><span class="o">();</span>
<span class="kt">long</span> <span class="n">test3</span> <span class="o">=</span> <span class="n">test3</span><span class="o">();</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span>
<span class="s">"Test #1 (concat): %d\nTest #2 (String.format): %d\nTest #3 (StringBuilder): %d\n"</span><span class="o">,</span>
<span class="n">test1</span><span class="o">,</span> <span class="n">test2</span><span class="o">,</span> <span class="n">test3</span><span class="o">));</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kt">long</span> <span class="nf">test1</span><span class="o">()</span> <span class="o">{</span>
<span class="kt">long</span> <span class="n">tbegin</span> <span class="o">=</span> <span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">();</span>
<span class="n">String</span> <span class="n">str</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">long</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">5000</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="n">str</span> <span class="o">+=</span> <span class="s">"a = "</span> <span class="o">+</span> <span class="n">A</span> <span class="o">+</span> <span class="s">"\nb = "</span> <span class="o">+</span> <span class="n">B</span> <span class="o">+</span> <span class="s">"\nc = "</span> <span class="o">+</span> <span class="n">C</span>
<span class="o">+</span> <span class="s">"\nd = "</span> <span class="o">+</span> <span class="n">D</span> <span class="o">+</span> <span class="s">"\ne = "</span> <span class="o">+</span> <span class="n">E</span> <span class="o">+</span> <span class="s">"\nf = "</span> <span class="o">+</span> <span class="n">F</span> <span class="o">+</span> <span class="s">"\n"</span><span class="o">;</span>
<span class="o">}</span>
<span class="kt">long</span> <span class="n">tend</span> <span class="o">=</span> <span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">();</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="k">return</span> <span class="n">tend</span> <span class="o">-</span> <span class="n">tbegin</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kt">long</span> <span class="nf">test2</span><span class="o">()</span> <span class="o">{</span>
<span class="kt">long</span> <span class="n">tbegin</span> <span class="o">=</span> <span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">();</span>
<span class="n">String</span> <span class="n">str</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">long</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">5000</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="n">str</span> <span class="o">=</span> <span class="n">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"%sa = %f\nb = %d\nc = %d\nd = %c\ne = %b\nf = %s\n"</span><span class="o">,</span>
<span class="n">str</span><span class="o">,</span> <span class="n">A</span><span class="o">,</span> <span class="n">B</span><span class="o">,</span> <span class="n">C</span><span class="o">,</span> <span class="n">D</span><span class="o">,</span> <span class="n">E</span><span class="o">,</span> <span class="n">F</span><span class="o">);</span>
<span class="o">}</span>
<span class="kt">long</span> <span class="n">tend</span> <span class="o">=</span> <span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">();</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="k">return</span> <span class="n">tend</span> <span class="o">-</span> <span class="n">tbegin</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kt">long</span> <span class="nf">test3</span><span class="o">()</span> <span class="o">{</span>
<span class="kt">long</span> <span class="n">tbegin</span> <span class="o">=</span> <span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">();</span>
<span class="n">StringBuilder</span> <span class="n">strb</span> <span class="o">=</span> <span class="k">new</span> <span class="n">StringBuilder</span><span class="o">();</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">long</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">5000</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="n">strb</span><span class="o">.</span><span class="na">append</span><span class="o">(</span><span class="s">"a = "</span><span class="o">).</span><span class="na">append</span><span class="o">(</span><span class="n">A</span><span class="o">);</span>
<span class="n">strb</span><span class="o">.</span><span class="na">append</span><span class="o">(</span><span class="s">"\nb = "</span><span class="o">).</span><span class="na">append</span><span class="o">(</span><span class="n">B</span><span class="o">);</span>
<span class="n">strb</span><span class="o">.</span><span class="na">append</span><span class="o">(</span><span class="s">"\nc = "</span><span class="o">).</span><span class="na">append</span><span class="o">(</span><span class="n">C</span><span class="o">);</span>
<span class="n">strb</span><span class="o">.</span><span class="na">append</span><span class="o">(</span><span class="s">"\nd = "</span><span class="o">).</span><span class="na">append</span><span class="o">(</span><span class="n">D</span><span class="o">);</span>
<span class="n">strb</span><span class="o">.</span><span class="na">append</span><span class="o">(</span><span class="s">"\ne = "</span><span class="o">).</span><span class="na">append</span><span class="o">(</span><span class="n">E</span><span class="o">);</span>
<span class="n">strb</span><span class="o">.</span><span class="na">append</span><span class="o">(</span><span class="s">"\nf = "</span><span class="o">).</span><span class="na">append</span><span class="o">(</span><span class="n">F</span><span class="o">).</span><span class="na">append</span><span class="o">(</span><span class="s">"\n"</span><span class="o">);</span>
<span class="o">}</span>
<span class="n">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">strb</span><span class="o">.</span><span class="na">toString</span><span class="o">();</span>
<span class="kt">long</span> <span class="n">tend</span> <span class="o">=</span> <span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">();</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="k">return</span> <span class="n">tend</span> <span class="o">-</span> <span class="n">tbegin</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p><b>Results:</b></p>
<pre>Test #1 (concat): 10734
Test #2 (String.format): 12516
Test #3 (StringBuilder): 16
Test #1 (concat): 10515
Test #2 (String.format): 12500
Test #3 (StringBuilder): 32
Test #1 (concat): 10485
Test #2 (String.format): 12515
Test #3 (StringBuilder): 31</pre>
<p>So the best result has test #3 (StringBuilder), the second one is concatenation with "+" operator and the worst one is String.format. The leadership of StringBuilder was expected for me, but out of the blue next to it is plain concatenation! The point is that plain concatenation uses StringBuilder. It's what JavaDoc says about this:</p>
<div style="background-color:#eeeeee;"><pre>
The Java language provides special support for the string concatenation operator ( + ), and for
conversion of other objects to strings. String concatenation is implemented through the StringBuilder
(or StringBuffer) class and its append method. String conversions are implemented through the method
toString, defined by Object and inherited by all classes in Java. For additional information on string
concatenation and conversion, see Gosling, Joy, and Steele, The Java Language Specification.</pre></div>
<p>The last one, String.format is very charming way which allows you to write easy-readable code. Unfortunately it's too slow, so it might be used carefully. But it's still so cool, so I'd rather use it unless very loaded parts of code.</p>Force cmd.exe to see PATH again2011-03-13T21:23:39+02:00Dmitriy Sukharevtag:sukharevd.net,2011-03-13:force-cmd-exe-to-see-path-again.html<p>Did your command line stop seeing files inside PATH? Do you think it's a
virus or a bug and just wanna pull down your system? Don't hurry up if so.
I had the same problem and finally I fixed it today. I'm not sure why did
this happen, probably it's due to installation of some changing PATH variable
applications which were installed recently, but I know how to fix it now.</p>
<p>The point is that path-variable is stored in the Windows registry. You can
find it here</p>
<pre>\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\Path</pre>
<p>Obviously installers and other programs are able (having rights) to change
this value. Unfortunately some of them do it incorrectly. Normal type of this
registry value is REG_EXPAND_SZ, I had just REG_SZ. The difference is that
saying about REG_EXPAND_SZ Windows automatically replaces all variables inside
percent signs (like %SystemRoot%) with proper address (like C:\Windows),
and Windows doesn't change REG_SZ at all. It goes without saying that command
line can't invoke ping, ipconfig, calc, etc. directly if type of the registry
value is REG_SZ. Now check your variable's type.</p>
<div style="text-align:center">
<a href="http://sukharevd.net/static/files/blog/wincmd/win_path_regedit.png"
rel="lightbox"
title="REG_SZ is a wrong type for PATH variable">
<img class="link"
src="http://sukharevd.net/static/files/blog/wincmd/win_path_regedit50.png"
alt="REG_SZ is a wrong type for PATH variable" />
</a>
</div>
<p>If it's REG_SZ, the only thing you have to do for repairing a proper work of
cmd.exe is changing PATH variable via Windows' Environment Variables dialog
(Win+Break ⇒ Advanced ⇒ Environment Variables). System'll
automatically restore it to the right type. If you don't want to change anything
in your PATH, you can just save it twice, for instance adding and deleting some
symbol. Take into account that if you just open changing dialog and press OK,
nothing'll change, you HAVE TO CHANGE this string.</p>
<p>If your PATH variable has REG_EXPAND_SZ type and you still have this problem,
keep googling.</p>How did I configure Ubuntu2011-03-04T01:36:10+02:00Dmitriy Sukharevtag:sukharevd.net,2011-03-04:how-did-i-configure-ubuntu.html<p>As they say there are two types of administrators: who do backups and who
already do :) Unfortunately I began to think about this too late and as result
I had to reinstall my system and configure it from scratch. In this article I'm
describing how I did most steps of configuration stage. The main aim of
article is just to be the checklist and crib for ME, but it can be useful for
others at the same time. Beneath I'll describe installation of applications
which I consider suitable after little bit more than a year experience of
using Ubuntu. Big part of that applications aren't used by most Linux users so
be careful, don't resist the temptation to install unnecessary programs. I'll
make short description for them.</p>
<h2>Content</h2>
<ol>
<li><a href="#before">Before reinstallation</a></li>
<li><a href="#install">Notice to installation</a></li>
<li><a href="#update">Update</a></li>
<li><a href="#rep">Adding Canonical Partner Repositories</a></li>
<li><a href="#apps">Installation of my favourite applications</a></li>
<li><a href="#post">Postinstallation configurations</a></li>
</ol>
<h2 id="before">Stage 1. Before reinstallation</h2>
<p>If you have a linux-like operating system whose death you want, consider an idea of transfering some configurations you already have. Otherwise skip this stage.</p>
<p>Most programs store their setting in folder /home/<user name>/<program name>, so</p>
<blockquote>
<p>Copy your home directory to a safe place.</p>
</blockquote>
<p>I have Apache HTTP Server and some other apps whose config-files live in /etc/ folder, therefore answer the question</p>
<blockquote>
<p>Do you have some important for you config-files in /etc/? Don't you know? Then you can just skip it, you would know if you had. Otherwise copy them to a safe place. I just copied whole /etc/ folder (it was very small).</p>
</blockquote>
<p>By the way</p>
<blockquote>
<p>There is also <b>fstab</b> file in the /etc/ which allows to mount some file systems permamently (like NTFS ones). If you changed fstab (or any other file of etc), consider coping /etc/ once more.</p>
</blockquote>
<p>The third place which I think might have important files is /var/. It contains among other things content of your web- (app-, svn-) servers. Don't forget to copy it if you have any.</p>
<blockquote>
<p>Make backups of browser bookmarks if you have any.</p>
</blockquote>
<h2 id="install">Stage 2. Notice to installation</h2>
<p>Ubuntu installation is very easy process, even easier than Windows' one I think. The only thing you can spoil is partitioning. What was NOT obvious for me is that the top diagram is before-state of your disk and bottom diagram is after-state.</p>
<div style="text-align:center"><a href="http://sukharevd.net/static/files/blog/ubuntu_install/ubuntu_partitioning.png" rel="lightbox" title="Partitioning"><img class="link" src="http://sukharevd.net/static/files/blog/ubuntu_install/ubuntu_partitioning50.png" alt="partitioning" /></a></div>
<p>But if you have experience with partitioning in Linux I guess "advanced" option will be the best choise.</p>
<p>If you're Windows user take into account that Ubuntu traditionally uses ext3 or ext4 file-systems (not NTFS), mount points ('/' for instance) and separate partitions for swap.</p>
<h2 id="update">Stage 3. Update</h2>
<p>Sometimes some things don't work just after installation. Don't panic, try update in this case.</p>
<h2 id="rep">Stage 4. Adding Canonical Partner Repositories</h2>
<p>To install certain applications (like Skype or Sun JDK) from repositories you have to add them to repositories firstly. More details you can find <a target="_blank" href="https://help.ubuntu.com/community/Repositories/Ubuntu#Adding_Repositories_in_Ubuntu">here</a>. Execute following:</p>
<ol>
<li>System ⇒ Administration ⇒ Synaptic Package Manager;</li>
<li>Settings ⇒ Repositories ⇒ Other Software;</li>
<li>Choose http://archive.canonical.com/ubuntu partner repositories and press "Close".</li>
</ol>
<h2 id="apps">Stage 5. Installation of my favourite applications</h2>
<ol>
<li>Create file on the desktop with name installapps.sh (or any other), open it and insert there following text
<pre># GENERAL UTILITIES
sudo apt-get install alarm-clock goldendict mc nvclock osmo p7zip ttf-ubuntu-font-family lm-sensors
sudo apt-get install bum
#sudo sensors-detect
# GRAPHICS
sudo apt-get install gimp mypaint
# >> pinta block start
sudo add-apt-repository ppa:moonlight-team/pinta
sudo apt-get update
sudo aptitude install pinta
# << pinta block end
# OFFICE
sudo apt-get install openoffice.org-style-galaxy
# INTERNET
sudo apt-get install chromium-browser deluge thunderbird pidgin skype rtorrent
# skype need canonical partners' repository (see stage 4)
# AUDIO & VIDEO
sudo apt-get install amarok libxine1-ffmpeg gstreamer0.10-plugins-ugly ubuntu-restricted-extras
sudo apt-get install arista brasero easytag entagged pulseaudio pavucontrol
sudo apt-get install soundconverter sound-juicer gtk-recordmydesktop vlc totem
sudo /usr/share/doc/libdvdread4/install-css.sh
# SOFTWARE DEVELOPING & SERVERS
sudo apt-get install sun-java6-jdk sun-java6-source openjdk-6-jdk apache2 tomcat6 libapache2-mod-jk
sudo apt-get install mysql-server subversion ant maven2 php5 php5-mysql php5-mcrypt g++
</pre></li>
<li>Delete unnecessary for you applications. Look for short descriptions beneath.</li>
<li>Save file</li>
<li>Run terminal (Application ⇒ Accessories). Type
<pre>cd ~/Desktop/
sudo sh installapps.sh</pre></li>
</ol>
<h3>Descriptions</h3>
<p>Delete applications which you don't need from the file.</p>
<h4>GENERAL UTILITIES</h4>
<ol>
<li><b>alarm-clock</b> - alarm clock and countdown timer;</li>
<li><b>goldendict</b> - great dictionary. But still open-source so you have to add dictionaries manually. Can use web-pages as dictionaries (for instance Google Translate)!!!</li>
<li><b>mc</b> - great CLI file manager like Norton Commander. The best replace for FAR and Total Commander;</li>
<li><b>nvclock</b> - utility for nVidia graphic cards. I use it to see temperature of GPU. WARNING: NVIDIA ONLY!!! Don't install it if you don't know what does it mean;</li>
<li><b>osmo</b> - organiser;</li>
<li><b>p7zip</b> - great archiver, contains a lot of amazing formats;</li>
<li><b>ttf-ubuntu-font-family</b> - Ubuntu font, appeared in Ubuntu 10.10;</li>
<li id="sensors"><b>lm-sensors</b> - CLI utility, show state of your hardware (temperature, speed of coolers, voltage). Need configurating (run sudo sensors-detect after finishing installation);</li>
<li><b>bum</b> - Boot-up manager - manager of startup and active daemons;</li>
</ol>
<h4>GRAPHICS</h4>
<ol>
<li><b>gimp</b> - Photoshop-like bitmap-editor;</li>
<li><b>mypaint</b> - bitmap-editor with rich set of brushes;</li>
<li><b>pinta</b> - Paint.NET-like bitmap-editor. Installs Mono (dotNet substitute). If you don't need it, delete the whole pinta block;</li>
</ol>
<h4>OFFICE</h4>
<ol>
<li id="ooostyle"><b>openoffice.org-style-galaxy</b> - icon-theme for OpenOffice which is default in Windows. I think it looks better. After installation to change style go to OpenOffice Tools - Options - OpenOffice - View;</li>
</ol>
<h4>INTERNET</h4>
<ol>
<li><b>chromium-browser</b> - Google Chrome;</li>
<li><b>deluge</b> - torrent-client. Not very good due to huge CPU resources usage;</li>
<li><b>thunderbird</b> - Mozilla Thunderbird email-client;</li>
<li><b>pidgin</b> - IM manager which support ICQ, GoogleTalk, Yahoo, AIM and a lot other protocols;</li>
<li><b>skype</b> - Skype;</li>
<li><b>rtorrent</b> - CLI torrent-client with low resources usage rate. You need to learn how to use it.</li>
</ol>
<h4>AUDIO & VIDEO</h4>
<ol>
<li><b>amarok</b> - great iTunes-like audio player. Based on KDE so it uses a lot of RAM, but I love it. Needs <i>libxine1-ffmpeg, gstreamer0.10-plugins-ugly and ubuntu-restricted-extras</i> to play mp3, wav, wma and other commercial formats;</li>
<li><b>ubuntu-restricted-extras</b> - includes restricted commercial formats like mp3, microsoft fonts, etc.</li>
<li><b>arista</b> - media files converter;</li>
<li><b>brasero</b> - utility for writing CD/DVD disks;</li>
<li><b>easytag, entagged</b> - utilities for changing tags of music files;</li>
<li><b>pavucontrol</b> - GUI volume control for PulseAudio;</li>
<li><b>soundconverter</b> - audio converter;</li>
<li><b>sound-juicer</b> - audio CD ripper;</li>
<li><b>gtk-recordmydesktop</b> - utility for recording video from you desktop and your microphone, or soundcard output (read <a target="_blank" href="http://unix.stackexchange.com/questions/3490/how-can-i-record-the-sound-output-with-gtk-recordmydesktop">this</a>);</li>
<li><b>vlc, totem</b> - video players;</li>
<li><b>install-css.sh</b> - add DVD support. Read about restricted formats and DVD-Video <a target="_blank" href="https://help.ubuntu.com/community/RestrictedFormats">here</a>;</li>
</ol>
<h4>SOFTWARE DEVELOPING & SERVERS</h4>
<ol>
<li><b>sun-java6-jdk</b> - Sun's JDK;</li>
<li><b>sun-java6-source</b> - contains sources of Java API classes;</li>
<li><b>openjdk-6-jdk</b> - free open source JDK;</li>
<li><b>apache2</b> - Apache HTTP Server;</li>
<li><b>tomcat6</b> - Apache Tomcat 6;</li>
<li><b>libapache2-mod-jk</b> - mod_jk for connecting Apache HTTP Server with Jave application server;</li>
<li><b>mysql-server</b> - MySQL server(!);</li>
<li><b>subversion</b> - SVN utilities + SVN server (svnserve);</li>
<li><b>ant, maven2</b> - Java build tools;</li>
<li><b>php5, php5-mysql, php5-mcrypt</b> - PHP packages: main, connector with MySQL server and mcrypt (needed for phpMyAdmin);</li>
<li><b>g++</b> - CLI C++ compiler;</li>
</ol>
<h4>OTHER APPLICATIONS</h4>
<p>Some other applications (for instance <b>VirtualBox, Dropbox, Opera</b>) you can install downloading binary files by browser.</p>
<h2 id="post">Stage 6. Postinstallation configurations</h2>
<p>Now you can copy your backed up applications' configs to your system.</p>
<p>Don't forget to configure applications which need confugurating before the first usage: <a href="#sensors">lm-sensors</a>, <a href="#ooostyle">galaxy style for OpenOffice</a>, rtorrent.</p>
<p>Read how to hide removable drives from desktop <a target="_blank" href="http://www.howtogeek.com/howto/ubuntu/hide-removable-drive-icons-from-your-ubuntu-desktop/">here</a>.</p>
<p>Change buttons in address line to text-field by doing <a target="_blank" href="http://ubuntuforums.org/showpost.php?p=417775&postcount=1">this</a>. If Applications menu doesn't contain Configuration Editor, it's also available by pressing Alt-F2 and typing gconf-editor.</p>
<p>Easy way of changing icons size of Gnome you can find <a target="_blank" href="http://www.linuxquestions.org/questions/suse-novell-60/desktop-icon-size-in-gnome-configurable-381182/#post2643060">here</a>.</p>Making backups of ext4 partitions with FSArchiver2011-02-21T23:57:14+02:00Dmitriy Sukharevtag:sukharevd.net,2011-02-21:making-backups-of-ext4-partitions-with-fsarchiver.html<p>In this article I'll write how I made backup of system ext4 partition using
FSArchiver tool for Linux.</p>
<p>Since I've changed file system of my Ubuntu partition to ext4,
<code>partimage</code> couldn't create backups from it anymore. So I had to
choose another utility instead. I stopped at FSArchiver. It's a CLI utility
and whole backup process triggers by only one command.</p>
<p>I backed up my system partition, therefore it was necessary to use live-cd
Linux (in my case <code>SystemRescueCd</code>). So firstly I had to mount
partition for storing backup image:</p>
<div class="highlight"><pre><span class="nv">$ </span>mkdir /media/backup/
<span class="nv">$ </span>mount /dev/sda4 /media/backup
</pre></div>
<p>And after this a single command was necessary to backup my /dev/sda6 partition:</p>
<div class="highlight"><pre><span class="nv">$ </span>fsarchiver -j2 -z9 -L<span class="s2">"Description of image"</span> -s2037 savefs /media/backup/sda420110221.fsa /dev/sda6
</pre></div>
<p>which means that compression must be processed by two threads (I have 2 cores)
with the 9th (highest) level of compression. Image must be splited into the
parts with size 2037 MB and it will have description written insidethe quotes.</p>
<p>It took a lot of time (like 20 minutes) even for partition with only 7GB of
information so choose lower level of compression if you hurry up.</p>
<p>You can find quick start about FSArchiver
<a href="http://www.fsarchiver.org/QuickStart" target="_blank">here</a>.
It looks like there is everything you have to know to start usage FSArchiver.</p>Setting up environment for JEE development under Ubuntu/Debian2011-01-18T18:24:41+02:00Dmitriy Sukharevtag:sukharevd.net,2011-01-18:environment-for-j2ee-development-under-ubuntu.html<p><em>Last modification: 2013-10-23 (<a target="_blank" href="http://sukharevd.kiev.ua/blog.php?id=8">previous version</a>)</em></p>
<p>In this article I'm going to collect short descriptions about how to rapidly set up base stuff for Java web-application
development. Please note that you don't have to install each application mentioned here, one item from every content's
section (see below) will probably be enough. Also in some sections you can find tabs with different ways of installation,
usually it's installation from repository and installation from tarballs. Repository way is much easier, but might require
more traffic and disk space, and vice versa for tarballs. Please select tabs that are more appropriate for you.</p>
<p>Personally I use Debian Wheezy, but I also tested material for this article under Ubuntu 12.04 and 13.10. I have Oracle JDK installed,
use easier "repository way" for Ant and Maven, and tarball way for Tomcat.</p>
<h2>Content</h2>
<ol style="list-style-type:decimal">
<li>JDK:
<ul style="list-style-type:circle">
<li><a href="#oraclejdk">Oracle JDK</a></li>
<li><a href="#openjdk">OpenJDK</a></li>
</ul>
</li>
<li>Building Tools:
<ul style="list-style-type:circle">
<li><a href="#maven">Maven</a></li>
<li><a href="#ant">Ant</a></li>
</ul>
</li>
<li>Web & Application Servers:
<ul style="list-style-type:circle">
<li><a href="#tomcat">Tomcat</a></li>
<li><a href="#jboss">JBoss AS and Wildfly</a></li>
</ul>
</li>
<li>IDE:
<ul style="list-style-type:circle">
<li><a href="#eclipse">Eclipse</a></li>
</ul>
<ul style="list-style-type:circle">
<li><a href="#eclipsetomcat">Tomcat integration with Eclipse</a></li>
</ul>
</li>
<li>DBMS:
<ul style="list-style-type:circle">
<li><a href="#mysql">MySQL</a></li>
</ul>
</li>
<li>
<a href="#change-default-jvm">How to change default JVM</a>
</li>
</ol>
<h2 id="jdk">JDK installation</h2>
<p>Before it's too late I'd like to say that if you can't answer the question "What is JDK?",
you probably better start from Java SE and postpone Java EE stuff.</p>
<p>Which JDK to choose? I noticed that most developers (including me) prefer Oracle JDK over OpenJDK,
but I can't provide hard evidence why it's better, in general they're pretty much the same. So it's
your choice which one to use.</p>
<h3 id="oraclejdk">Oracle JDK Installation</h3>
<p>Automated Oracle JDK 7 installation script for major Linux distributions
is provided in my article <a target="_blank" href="http://sukharevd.net/install-oracle-jdk-7-in-3-simple-steps.html">Install Oracle JDK 7 in 3 simple steps</a>.</p>
<h3 id="openjdk">OpenJDK Installation</h3>
<p>To install OpenJDK 7 execute the command in terminal*:
<pre class="brush: bash; auto-links: false; toolbar: false;">sudo apt-get install openjdk-7-jdk</pre></p>
<p>To check if openJDK was installed fine execute following command:
<pre class="brush: bash; auto-links: false; toolbar: false;">java -version</pre></p>
<p>If everything is good you will see something like
<pre>java version "1.7.0_25"
OpenJDK Runtime Environment (IcedTea 2.3.10) (7u25-2.3.10-1ubuntu0.12.04.2)
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)</pre></p>
<p>If installation finished without errors, but a different version of JVM is shown,
after installing other tools open <a target="_blank" href="#change-default-jvm">this simple guide</a> to change it
to openjdk-7 version.</p>
<p>* If you are not using Ubuntu, and you don't know who are sudoers, please execute commands here as super user (root).
For this type `su -` in terminal, and input root's password, you should know it. When you are done here please don't
use that terminal, just close it. As super user you can skip typing sudo.</p>
<h2 id="build">Building tools installation</h2>
<p>Which building tool to use? As for me Maven and Ant are pretty much different tools. Maven is easier and
more convenient to use for typical projects, and it's not only building tool. Ant is more flexible and
harder to use, I think it's possible to say that it's more low-level tool. Personally I worked with Ant first.</p>
<h3 id="ant">Ant Installation</h3>
<section class="tabs">
<ul class="tab-nav">
<li class="active"> <a href="#">Repository way</a></li>
<li><a href="#">Tarball way</a></li>
</ul>
<div class="tab-content active">
<p>To install Ant execute the following command in terminal:
<pre>sudo apt-get install ant</pre></p>
<p>It might happen that Ant installation will rewrite your default Java version (you can
check it executing `java -version` in terminal). If so, after installing other tools
you can find a <a target="_blank" href="#change-default-jvm">simple guide</a> to change it
back in the very end of this article.</p>
<!--<p>To check if Ant was installed fine execute following command:
<pre>ant</pre></p>
<p>If everything's good you will see something like
<pre>Buildfile: build.xml does not exist!
Build failed</pre></p>-->
</div>
<div class="tab-content">
<p>
You can download binaries from <a target="_blank" href="http://ant.apache.org/bindownload.cgi">Apache's site</a>.
In this case
you will download only about 5MB. And it will not rewrite default java version, but
you will have to update Ant manually.
Run terminal, change directory to where your downloaded tar.gz file is and execute
following commands
</p>
<pre># Don't forget to change version in the next 2 lines
sudo tar -xvzf apache-ant-1.9.2-bin.tar.gz -C /opt
sudo ln -s /opt/apache-ant-1.9.2/ /opt/ant
echo 'export ANT_HOME=/opt/ant' > /tmp/ant.sh
echo 'export PATH=$ANT_HOME/bin:$PATH' >> /tmp/ant.sh
sudo mv /tmp/ant.sh /etc/profile.d/
source /etc/profile.d/ant.sh</pre>
</div>
</section>
<p>To check if Ant was installed successfully execute following command: <pre>ant -version</pre></p>
<p>You should see something like
<pre>Apache Ant(TM) version 1.9.2 compiled on July 8 2013</pre></p>
<h3 id="maven">Maven Installation</h3>
<section class="tabs">
<ul class="tab-nav">
<li class="active"> <a href="#">Repository way</a></li>
<li><a href="#">Tarball way</a></li>
</ul>
<div class="tab-content active">
<p>To install Maven's package execute the following commands in terminal:
<pre class="brush: bash; auto-links: false; toolbar: false;">sudo apt-get install maven</pre></p>
<p>It might happen that Maven installation will rewrite your default Java version (you can
check it executing `java -version` in terminal). If so, after installing other tools
you can find a <a target="_blank" href="#change-default-jvm">simple guide</a> to change it
back in the very end of this article.</p>
</div>
<div class="tab-content">
<p>You have an option to download and install Maven from Apache's site. In this case
you will download only about 5MB. And it will not rewrite default java version, but
you will have to update it manually. For this download the latest Maven version from
<a target="_blank" href="http://maven.apache.org/download.cgi">here</a> as binary tar.gz.</p>
<p>Run terminal, change directory to where your downloaded tar.gz file is and execute
following commands</p>
<pre class="brush: bash; auto-links: false; toolbar: false;">
# Don't forget to change version in the next 2 lines
sudo tar -xvzf apache-maven-3.1.1-bin.tar.gz -C /opt
sudo ln -s /opt/apache-maven-3.1.1/ /opt/maven
echo 'export PATH=/opt/maven/bin:$PATH' > /tmp/maven.sh
sudo mv /tmp/maven.sh /etc/profile.d/
source /etc/profile.d/maven.sh</pre>
</div>
</section>
<p>Let's check if Maven was properly installed. Run in terminal</p>
<div class="highlight"><pre><span class="n">mvn</span> <span class="o">-</span><span class="n">version</span>
</pre></div>
<p>If everything's OK, you should see something like</p>
<div class="highlight"><pre>Apache Maven 3.1.1 (0728685237757ffbf44136acec0402957f723d9a; 2013-09-17 08:22:22-0700)
Maven home: /opt/apache-maven-3.1.1
Java version: 1.7.0_40, vendor: Oracle Corporation
Java home: /usr/lib/jvm/jdk1.7.0_40/jre
Default locale: en_CA, platform encoding: UTF-8
OS name: "linux", version: "3.8.0-29-generic", arch: "amd64", family: "unix"
</pre></div>
<h2 id="servers">Server installation</h2>
<p>While you don't use full stack of Java EE technologies (including EJB, JNDI, etc.), you may
use containers like Tomcat or Jetty. They let you deploy web-applications that use
JSP & Servlet API. Containers should work for you for most projects.</p>
<h3 id="tomcat">Tomcat Installation</h3>
<section class="tabs">
<ul class="tab-nav">
<li class="active"> <a href="#">Repository way</a></li>
<li><a href="#">Tomcat 7 tarball way</a></li>
<li><a href="#">Tomcat 8 tarball way</a></li>
</ul>
<div class="tab-content active">
<p>To install Tomcat 7 from repository execute the following command in terminal:
<pre>sudo apt-get install tomcat7</pre></p>
<p>It might happen that Tomcat installation will rewrite your default Java version (you can
check it executing `java -version` in terminal). If so, after installing other tools
you can find a <a target="_blank" href="#change-default-jvm">simple guide</a> to change it
back in the very end of this article.</p>
</div>
<div class="tab-content">
<p>Download Tomcat from <a target="_blank" href="http://tomcat.apache.org/download-70.cgi">Apache's site</a>.
In this case you will download only about 8MB. And it will not rewrite default java version, but
you will have to update Tomcat manually.</p>
<p>Run terminal, change directory to where your downloaded tar.gz file is and execute
following commands (after the first sudo-wrapped command you can copy-past others at once).</p>
<pre># Don't forget to change version in the next 2 lines
sudo tar -xzf apache-tomcat-7.0.42.tar.gz -C /opt # extract archieve
sudo ln -s /opt/apache-tomcat-7.0.42/ /opt/tomcat7 # create link for conveniece
sudo useradd -s /sbin/nologin tomcat7 # add user to run tomcat service
sudo chown -R tomcat7:tomcat7 /opt/tomcat7 # and give it ownership
sudo chown -R tomcat7:tomcat7 /opt/tomcat7/ # to tomcat's directory
cat > /tmp/tomcat7 << "EOF"
#!/bin/sh
### BEGIN INIT INFO
# Provides: tomcat7
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/Stop Apache Tomcat 7
### END INIT INFO
TOMCAT_USER=tomcat7
TOMCAT_DIR=/opt/tomcat7
case "$1" in
start)
echo "Starting Apache Tomcat 7..."
su - $TOMCAT_USER -s /bin/bash -c "$TOMCAT_DIR/bin/startup.sh"
exit $?
;;
stop)
echo "Stopping Apache Tomcat 7..."
su - $TOMCAT_USER -s /bin/bash -c "$TOMCAT_DIR/bin/shutdown.sh"
exit $?
;;
restart)
$0 stop
$0 start
exit $?
;;
*)
echo "Usage: /etc/init.d/tomcat7 {start|stop|restart}"
exit 1
;;
esac
exit 0
EOF
sudo mv /tmp/tomcat7 /etc/init.d/tomcat7 # register tomcat as service
sudo chmod 755 /etc/init.d/tomcat7 # make it executable
sudo service tomcat7 start # run tomcat as service
sudo update-rc.d tomcat7 defaults # make tomcat run with system</pre>
</div>
<div class="tab-content">
<p>Download Tomcat from <a target="_blank" href="http://tomcat.apache.org/download-80.cgi">Apache's site</a>.
In this case you will download only about 8MB. And it will not rewrite default java version, but
you will have to update Tomcat manually.</p>
<p>Be aware that Eclipse doesn't support the 8th version at present, so you will have to deploy your
applications manually.</p>
<p>Run terminal, change directory to where your downloaded tar.gz file is and execute
following commands (after the first sudo-wrapped command you can copy-past others at once).</p>
<pre># Don't forget to change version in the next 2 lines
sudo tar -xzf apache-tomcat-8.0.0-RC5.tar.gz -C /opt # extract archieve
sudo ln -s /opt/apache-tomcat-8.0.0-RC5/ /opt/tomcat8 # create link for conveniece
sudo useradd -s /sbin/nologin tomcat8 # add user to run tomcat service
sudo chown -R tomcat8:tomcat8 /opt/tomcat8 # and give it ownership
sudo chown -R tomcat8:tomcat8 /opt/tomcat8/ # to tomcat's directory
cat > /tmp/tomcat8 << "EOF"
#!/bin/sh
### BEGIN INIT INFO
# Provides: tomcat8
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/Stop Apache Tomcat 8
### END INIT INFO
TOMCAT_USER=tomcat8
TOMCAT_DIR=/opt/tomcat8
case "$1" in
start)
echo "Starting Apache Tomcat 8..."
su - $TOMCAT_USER -s /bin/bash -c "$TOMCAT_DIR/bin/startup.sh"
exit $?
;;
stop)
echo "Stopping Apache Tomcat 8..."
su - $TOMCAT_USER -s /bin/bash -c "$TOMCAT_DIR/bin/shutdown.sh"
exit $?
;;
restart)
$0 stop
$0 start
exit $?
;;
*)
echo "Usage: /etc/init.d/tomcat8 {start|stop|restart}"
exit 1
;;
esac
exit 0
EOF
sudo mv /tmp/tomcat8 /etc/init.d/tomcat8 # register tomcat as service
sudo chmod 755 /etc/init.d/tomcat8 # make it executable
sudo service tomcat8 start # run tomcat as service
sudo update-rc.d tomcat8 defaults # make tomcat run with system</pre>
</div>
</section>
<p>To check if Tomcat was installed correctly launch your web browser and visit address
<code>http://localhost:8080/</code>. If everything is fine you will see page like a following:</p>
<p><a href="http://sukharevd.net/static/files/blog/java2ee/tomcat-welcome-page.png" rel="lightbox" title="Tomcat: It Works Page"><img class="link" alt="Tomcat: It Works Page" src="http://sukharevd.net/static/files/blog/java2ee/tomcat-welcome-page50.png" /></a></p>
<p>Now tomcat is a daemon in your system and will start up with every loading of your system. You can
stop it, start it and restart it executing following commands (change tomcat7 to tomcat8 if you
installed the 8th version)</p>
<div class="highlight"><pre>sudo service tomcat7 stop
sudo service tomcat7 start
sudo service tomcat7 restart
</pre></div>
<h3 id="jboss">JBoss AS and Wildfly Installation</h3>
<p>I wrote two articles about automatical installation of these two application servers. The only two
things you need to do is to execute two commands (to download and to run script that installs
application server).
Follow one of these links:
<ul>
<li><a target="_blank" href="http://sukharevd.net/jboss-as-7-configuration.html">Install JBoss AS 7</a></li>
<li><a target="_blank" href="http://sukharevd.net/wildfly-8-installation.html">Install Wildfly 8</a></li>
</ul>
Be aware that Wildfly is just a new name for JBoss AS starting from version 8.</p>
<h2 id="eclipse">Eclipse Installation</h2>
<ol style="list-style-type:decimal">
<li>Download Eclipse from the official <a target="_blank" href='http://www.eclipse.org/downloads/'>Eclipse's website</a>.
Choose "Eclipse IDE for Java EE Developers" edition instead of "Eclipse IDE for Java Developers" because the last one is just for Java SE and isn't very suitable for creation web-applications.</li>
<li>Uncompress downloaded archive into folder you are used to use as folder for user-installed applications.
Run terminal, change directory to where your downloaded tar.gz file is and execute the following commands
<pre class="brush: bash; auto-links: false; toolbar: false;">sudo tar -xvzf eclipse-jee-<version>-linux-gtk.tar.gz -C /opt
sudo mv /opt/eclipse /opt/eclipse-jee</pre></li>
<li>Add a link to Eclipse in your Applications menu:
<ol style="list-style-type:lower-alpha">
<li>For some reason Ubuntu doesn't have Main Menu editor nowadays by default.
So I recommend to install it. It will help you to add your own launchers to main menu.
<pre>sudo apt-get install alacarte</pre></li>
<li>Menu ⇒ Main Menu. You can launch menu pressing Win key in both Gnome 3 (Debian) and Unity (Ubuntu).<br />
<!-- Press Alt+F2, type "alacarte", press Enter (or find 'Main Menu' in your menu).-->
<img class="link" alt="Main Menu with Alacarte selected" src="http://sukharevd.net/static/files/blog/java2ee/alacarte-launcher-in-main-menu.png" /></li>
<li>Programming ⇒ New Item<br />
<a href="http://sukharevd.net/static/files/blog/java2ee/eclipse-main-menu.png" rel="lightbox" title="Eclipse: Main Menu dialog"><img class="link" alt="Eclipse: Main Menu dialog" src="http://sukharevd.net/static/files/blog/java2ee/eclipse-main-menu50.png" /></a></li>
<li>Fill the fields like this:
<pre>Name: eclipse-jee
Command: /opt/eclipse-jee/eclipse
Comment: Eclipse IDE for Java EE Developers
Icon (press at the button): /opt/eclipse-jee/icon.xpm</pre>
<img src='http://sukharevd.net/static/files/blog/java2ee/eclipse-launcher.png' alt='Eclipse: Launcher dialog' /><br />
and press Close;</li>
<li>Eclipse item should have appeared in your menu. Press 'Close' button to close Main Menu editing dialog.<br />
<a href="http://sukharevd.net/static/files/blog/java2ee/eclipse-main-menu-after.png" rel="lightbox" title="Eclipse: Main Menu dialog"><img class="link" alt="Eclipse: Main Menu dialog" src="http://sukharevd.net/static/files/blog/java2ee/eclipse-main-menu-after50.png" /></a></li>
<li>For some reason I had to reboot machine after adding this launcher using alacarte in Ubuntu before it appeared. Maybe you too.</li>
</ol></li>
<li>Run Eclipse and check if you're able to run a simple java application (Hello world, for example)</li>
</ol>
<h2 id="eclipsetomcat">Tomcat integration with Eclipse</h2>
<ol style="list-style-type:decimal">
<li>Run Eclipse. Add Tomcat server into a workspace doing following:<br />
<ol style="list-style-type:lower-alpha">
<li><pre>File ⇒ New ⇒ Other... ⇒ Servers ⇒ Server ⇒ Next ></pre></li>
<li>Choose <pre>Apache ⇒ Tomcat v7.0 Server</pre>and click 'Next >'</li>
<li>Set Tomcat Installation Directory: /opt/tomcat7 (or /opt/tomcat8, or /usr/share/tomcat7 if installed from repo)</li>
<li>Click Finish. I had some 'permission denied' error, but after pressing Finish button again everything became good. If installed from repo, you will have error related with missed
config files instead. The same trick with pressing Finish one more time should work.</li>
</ol></li>
<li>Copy configurations in order to avoid that 'permission denied' or 'missed config file' problems: *<br />
<pre class="brush: bash; auto-links: false; toolbar: false;"># replace /opt/tomcat7/conf/ with /etc/tomcat7 if Tomcat was installed from repo
sudo cp -r /opt/tomcat7/conf/* \
~/workspace/Servers/Tomcat\ v7.0\ Server\ at\ localhost-config/
sudo chown -R $USER:$USER ~/workspace/Servers/Tomcat\ v7.0\ Server\ at\ localhost-config/</pre>
Take into account that Tomcat configurations in Eclipse and in /opt/tomcat7/ are different now.</li>
<li>If you installed Tomcat from repository, please concat policy files into one file, otherwise Eclipse will complain:
<pre>cd ~/workspace/Servers/Tomcat\ v7.0\ Server\ at\ localhost-config/
cat policy.d/* > catalina.policy</pre>
</li>
<li>Start server involving context menu of Tomcat in Servers tab (from the bottom Eclipse's panel) and clicking Start.<br />
If everything is good you'll see several lines in your Console tab after this action with only INFO and maybe WARN levels.
If you got errors try to refresh Server first, selecting it in left panel and pressing F5 button.</li>
<li>In case if your 8080 port is occupied with some application (like JBoss, Glassfish, another Tomcat, etc.) you need to replace all references to 8080, 8005, 8009 ports with some another unoccupied ones (for instance 9090, 9005, 9009). Do this by changing file Servers/Tomcat v7.0 Server at localhost-config/server.xml in the following way:
<p>Execute command: *<br /><pre class="brush: bash; auto-links: false; toolbar: false;">cd ~/workspace/Servers/Tomcat\ v7.0\ Server\ at\ localhost-config/
gedit server.xml</pre>and use replace (Ctrl+H) to change ports. After this restart Eclipse.</p>
</li>
<li>Open your favourite browser, type http://localhost:9090/ and press Enter.<br />
Error 404 is a good sign :)</li>
<li>Additionally you can create Dynamic web-application for checking purpose, but hardly does it concern installation topic, so I won't describe it here.</li>
</ol>
<p>* My workspace is ~/workspace/ folder, change commands if your one differs.</p>
<h2 id="mysql">MySQL</h2>
<p>While it's hard to imagine development of Java web-application without JDK, server, and friendly some building tool,
it's quite possible not to have relational database. But it's easy enough to install MySQL. Decide if you need it now.</p>
<p>To install MySQL execute the command:</p>
<div class="highlight"><pre><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="n">get</span> <span class="n">install</span> <span class="n">mysql</span><span class="o">-</span><span class="n">server</span>
</pre></div>
<p>and input a password for MySQL's root user.</p>
<p>To check if MySQL server was installed fine run the command:</p>
<div class="highlight"><pre><span class="n">mysql</span> <span class="o">-</span><span class="n">uroot</span> <span class="o">-</span><span class="n">p</span>
</pre></div>
<p>and enter password for your root account. Then you should see <code>mysql></code> prompt. Type <code>quit</code> to exit from it.</p>
<!--
<h2 id="oracledb">Oracle Database XE</h2>
<p>You can find really great manual about Oracle Database installation at <a target="_blank" href="http://www.cyberciti.biz/faq/howto-install-linux-oracle-database-xe-server/">this page</a>. The only think I want to add is that there's no versions of Oracle Db for x64 Linux systems.</p>
-->
<h2 id="change-default-jvm">How to change default JVM</h2>
<p>Fortunately there's a script that can change your default JVM. You can download and run this script executing commands:</p>
<div class="highlight"><pre>wget http://webupd8.googlecode.com/files/update-java-0.5b
chmod +x update-java-0.5b
sudo ./update-java-0.5b
</pre></div>
<p>It should open dialog where you can select version of JVM that you want to be your default one.</p>
<p><img class="link" alt="Dialog for changing default JVM" src="http://sukharevd.net/static/files/blog/java2ee/change-jvm.png" /></p>
<p>Press OK, and check that your default JVM has been changed:</p>
<div class="highlight"><pre>java -version
</pre></div>Usage of Oracle Database via JDBC2010-07-01T23:06:57+03:00Dmitriy Sukharevtag:sukharevd.net,2010-07-01:usage-of-oracle-database-via-jdbc.html<p>In this article I want to show you how to use Oracle Database via JDBC. I'm going to describe the easy way of connection to database, creation of table, and fetching, inserting, updating and deleting rows in created table (CRUD).</p>
<h2>What do you need for this?</h2>
<p>First of all you need an Oracle Database. I have 11g Express Edition version, which is free, so this text isn't only for very rich people paying a lot of money for their software, and so you can execute all steps from this little tutorial.</p>
<p>Let's launch browser and get all we need:</p>
<ol>
<li>Oracle Database Express Edition you can get <a href='http://www.oracle.com/technology/software/products/database/xe/index.html'>here</a><br /><!-- new link here will be http://www.oracle.com/technetwork/products/express-edition/downloads/index.html -->
Install it, and memorize password to have access to database, it will be used in the future.<br />
<a target='_blank' href='http://mikesmithers.wordpress.com/2011/11/26/installing-oracle-11gxe-on-mint-and-ubuntu/'>Here</a>
is a good manual how to install Oracle DB 11g XE in Ubuntu/Mint.<br />
<a target='_blank' href='http://www.davidghedini.com/pg/entry/install_oracle_11g_xe_on'>Here</a>
is a good manual how to install Oracle DB 11g XE in CentOS.<br />
For Windows installation is relatively easy.</li>
<li>Also you need for special JDBC driver to link Java and Oracle DB. You can get it <a target='_blank' href='http://www.oracle.com/technetwork/database/features/jdbc/index-091264.html'>here</a><br />
If you use IDE include jar-archive into projects worked with DBMS.</li>
</ol>
<h2>Wikipedia says</h2>
<p>JDBC (Java DataBase Connectivity) is an API for the Java programming language that defines how a client may access a database. It provides methods for querying and updating data in a database. JDBC is oriented towards relational databases.</p>
<p>A JDBC driver is a software component enabling a Java application to interact with a database.</p>
<p>In short, JDBC gives your applications an opportunity to make queries to database. Driver is usually a library for interaction with concrete DBMS.</p>
<h2>First job for your fingers</h2>
<p>Now you have all you need to write your the first program interacted with database.</p>
<p>First of all I propose to create an interface including methods for interaction with some DBMS. My variant is following:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">java.sql.Connection</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.sql.ResultSet</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.sql.SQLException</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Interface for interacting with database via JDBC driver.</span>
<span class="cm"> *</span>
<span class="cm"> * @author Sukharev Dmitriy</span>
<span class="cm"> *</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">DatabaseManager</span> <span class="o">{</span>
<span class="cm">/**</span>
<span class="cm"> * Loads JDBC driver.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">loadDriver</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">ClassNotFoundException</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Connects to database.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="n">Connection</span> <span class="nf">connectToDB</span><span class="o">(</span><span class="n">String</span> <span class="n">database</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">SQLException</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Disconnects from database.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">disconnectFromDB</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">)</span>
<span class="kd">throws</span> <span class="n">SQLException</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Executes query to database: create table.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">createTable</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">,</span> <span class="n">String</span> <span class="n">tablename</span><span class="o">)</span>
<span class="kd">throws</span> <span class="n">SQLException</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Executes query to database: fetch rows from database.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="n">ResultSet</span> <span class="nf">fetch</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">,</span> <span class="n">String</span> <span class="n">tablename</span><span class="o">)</span>
<span class="kd">throws</span> <span class="n">SQLException</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Prints result of fetching to console.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">printFetched</span><span class="o">(</span><span class="n">ResultSet</span> <span class="n">resultSet</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">SQLException</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Executes query to database: insert row to database.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">insert</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">,</span> <span class="n">String</span> <span class="n">tablename</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">SQLException</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Executes query to database: update rows of table.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">update</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">,</span> <span class="n">String</span> <span class="n">tablename</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">SQLException</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Executes query to database: delete rows from table.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">delete</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">,</span> <span class="n">String</span> <span class="n">tablename</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">SQLException</span><span class="o">;</span>
<span class="o">}</span>
</pre></div>
<!--<p>But don't be afraid, you don't have to type comments now as well as you don't have to type the whole text (it's a little bit borring;) ), you can add methods here just before realizing them in implemented classes. The whole list of methods are here only to acquaint you with purpose of all this methods. <i>I recommend you also not to copy-paste this (and all following) code to get more profit from the article</i>.</p>-->
<p>Now let's create class OracleDBManager which will implement previous interface. To have opportunity to compile this class before implementing all methods I propose to comment in interface all methods which are not realized and uncomment them after realizing one by one or realize empty methods.</p>
<h2>Load Driver</h2>
<p>First of all JDBC driver has to be loaded. There are several ways how-to do it, but here you'll see only one :). In the just created class OracleDBManager type following lines:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">java.sql.Connection</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.sql.ResultSet</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.sql.SQLException</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Loads Oracle JDBC driver.</span>
<span class="cm"> * </span>
<span class="cm"> * @throws ClassNotFoundException</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">loadDriver</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">ClassNotFoundException</span> <span class="o">{</span>
<span class="n">Class</span><span class="o">.</span><span class="na">forName</span><span class="o">(</span><span class="s">"oracle.jdbc.driver.OracleDriver"</span><span class="o">);</span>
<span class="o">}</span>
</pre></div>
<p>What these several lines actually do?</p>
<p>It's simple. Class.forName() is used for creation instance by name. This method throws exception if specified class wasn't found.</p>
<p>Why "oracle.jdbc.driver.OracleDriver"? It's also easy. If you open your Oracle's JDBC driver jar-archive (e.g. in 7zip or WinRAR) you'll find inside path oracle/jdbc/driver/ and class-file OracleDriver.class, so you are just loading this class :).</p>
<p>You need to load driver only once in application life-cycle. Actually you'll simply put launch of this method before all requests to database in application and won't remember about them after.</p>
<p>I hope now all is clear.<br /></p>
<p>Create also class Main which consists of method main(). Realize it in the following way:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">java.sql.Connection</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.sql.ResultSet</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.sql.SQLException</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Entry point of the application which shows how-to use JDBC driver</span>
<span class="cm"> * for interacting with MySQL and Oracle DB databases.</span>
<span class="cm"> *</span>
<span class="cm"> * @author Sukharev Dmitriy</span>
<span class="cm"> *</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
<span class="cm">/**</span>
<span class="cm"> * Uses entity of DatabasaManager interface for interacting with</span>
<span class="cm"> * MySQL or Oracle DB database using JDBC driver.</span>
<span class="cm"> *</span>
<span class="cm"> * @param args</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="n">DatabaseManager</span> <span class="n">dbManager</span> <span class="o">=</span> <span class="k">new</span> <span class="n">OracleDBManager</span><span class="o">();</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">dbManager</span><span class="o">.</span><span class="na">loadDriver</span><span class="o">();</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Driver was loaded."</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">ClassNotFoundException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">System</span><span class="o">.</span><span class="na">err</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Driver wasn't loaded."</span><span class="o">);</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>Compile and run it. Don't forget about driver's jar-archive which must be included.</p>
<p>If all is good you'll see "Driver was loaded" message, otherwise check if you didn't misspell and really included driver's jar-archive.</p>
<p>I believe that everything is OK now ;)</p>
<h2>Connect to Dababase</h2>
<p>Let's create connection to our database. Supplement your OracleDBManager class with following:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">java.sql.DriverManager</span><span class="o">;</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">user</span> <span class="o">=</span> <span class="s">"system"</span><span class="o">;</span> <span class="c1">// It's the main user of Oracle DB who had all</span>
<span class="c1">// privileges. It's study project so we can do</span>
<span class="c1">// this. But don't use system user in the real</span>
<span class="c1">// projects.</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">pw</span> <span class="o">=</span> <span class="s">"pw"</span><span class="o">;</span> <span class="c1">// Put here password you set for main user</span>
<span class="c1">// while installation.</span>
<span class="cm">/**</span>
<span class="cm"> * Connects to OracleDB.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="n">Connection</span> <span class="nf">connectToDB</span><span class="o">(</span><span class="n">String</span> <span class="n">database</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">SQLException</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">url</span> <span class="o">=</span> <span class="s">"jdbc:oracle:thin:@//localhost:1521/"</span> <span class="o">+</span> <span class="n">database</span><span class="o">;</span>
<span class="n">Connection</span> <span class="n">connection</span> <span class="o">=</span> <span class="n">DriverManager</span><span class="o">.</span><span class="na">getConnection</span><span class="o">(</span><span class="n">url</span><span class="o">,</span> <span class="n">user</span><span class="o">,</span> <span class="n">pw</span><span class="o">);</span>
<span class="k">return</span> <span class="n">connection</span><span class="o">;</span>
<span class="o">}</span>
</pre></div>
<p>You can see that you need for three strings to get connection: user, pw and url. I think you got meaning of the first two ones, but last is a little bit complex.</p>
<p>As far as you can see it looks like url in your browser with some little differences. The part before "//" is like "http:" in your browser. While you're using JDBC it always (constantly) starts from "jdbc" after which and before "//" is part that depends on your database and driver, you don't have to know about this more. The part after is like domain and subdomain, here you set name of host, port (but AFAIU it's not necessery for all BDMS and drivers if port is default), and name of database to which you wanna be connected.</p>
<p>Also pay your attention to the class DriverManager. It works with drivers, connections and tracing. Here we're using static method getConnection() returned instance of Connection class if specified url relates with a driver.</p>
<p>Now you can add launch of connectToDB() in your main() method surrounding it with try/catch block.</p>
<p>I remind that as you use Express Edition of Oracle DB you have only one database named "XE". So you don't need to think what database name to choose. Otherwise you have to declare an <i>existing</i> name of some database.</p>
<h2>Disconnect from Database</h2>
<p>After creation any connection have to be closed. For this aim there is exist method close() for any Connection instance. Just add this method to your Manager class:</p>
<div class="highlight"><pre><span class="cm">/**</span>
<span class="cm"> * Disconnects from OracleDB.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">disconnectFromDB</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">)</span>
<span class="kd">throws</span> <span class="n">SQLException</span> <span class="o">{</span>
<span class="n">connection</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="o">}</span>
</pre></div>
<p>It's reasonable to put launch of this method in finally-block where connection is in try-block in main() method.</p>
<p>Hereinafter I'll not describe main() method, just do it in your own way. In the end of article you can find link to the full source file set of current project.</p>
<h2>Create Table</h2>
<p>Let's create new table inside our database. To do this you have to write real Oracle DB query, even three. It's the most complex part of this article (at least if you don't know Oracle DB syntax). Now write following code:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">java.sql.Statement</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Executes query to OracleDB: create table. Last two queries are for</span>
<span class="cm"> * auto-increment of id-field.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">createTable</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">,</span> <span class="n">String</span> <span class="n">tablename</span><span class="o">)</span>
<span class="kd">throws</span> <span class="n">SQLException</span> <span class="o">{</span>
<span class="n">Statement</span> <span class="n">statement</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="na">createStatement</span><span class="o">();</span>
<span class="n">statement</span><span class="o">.</span><span class="na">executeUpdate</span><span class="o">(</span><span class="s">"CREATE TABLE "</span> <span class="o">+</span> <span class="n">tablename</span> <span class="o">+</span> <span class="s">" ("</span>
<span class="o">+</span> <span class="s">" id NUMBER(11) NOT NULL PRIMARY KEY,"</span>
<span class="o">+</span> <span class="s">" title VARCHAR2(100) NOT NULL,"</span>
<span class="o">+</span> <span class="s">" comments VARCHAR2(500) NULL,"</span> <span class="o">+</span> <span class="s">" price FLOAT NULL"</span> <span class="o">+</span> <span class="s">" )"</span><span class="o">);</span>
<span class="n">statement</span><span class="o">.</span><span class="na">executeUpdate</span><span class="o">(</span><span class="s">"CREATE SEQUENCE "</span> <span class="o">+</span> <span class="n">tablename</span> <span class="o">+</span> <span class="s">"_ID_SEQ"</span>
<span class="o">+</span> <span class="s">" START WITH 1"</span> <span class="o">+</span> <span class="s">" INCREMENT BY 1"</span> <span class="o">+</span> <span class="s">" NOMAXVALUE"</span><span class="o">);</span>
<span class="n">statement</span><span class="o">.</span><span class="na">executeUpdate</span><span class="o">(</span><span class="s">"CREATE OR REPLACE TRIGGER "</span> <span class="o">+</span> <span class="n">tablename</span>
<span class="o">+</span> <span class="s">"_ID_TRIGGER"</span> <span class="o">+</span> <span class="s">" BEFORE INSERT ON "</span> <span class="o">+</span> <span class="n">tablename</span>
<span class="o">+</span> <span class="s">" REFERENCING NEW AS NEW OLD AS OLD FOR EACH ROW"</span> <span class="o">+</span> <span class="s">" BEGIN"</span>
<span class="o">+</span> <span class="s">" SELECT "</span> <span class="o">+</span> <span class="n">tablename</span>
<span class="o">+</span> <span class="s">"_ID_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL; "</span> <span class="o">+</span> <span class="s">" END;"</span><span class="o">);</span>
<span class="o">}</span>
</pre></div>
<p>In the first line of the method we're getting Statement instance which is an operation system resource. Javadocs say about this: "The object used for executing a static SQL statement and returning the results it produces."</p>
<p>There are two types of SQL statements. The first one just gets information from database and doesn't change it. Use executeQuery() method of Statement instance for such statements. The second type used for changing database. Use executeUpdate() method for them.</p>
<p>So the last part of method includes three executeUpdate methods. It's reasonable because we change database by creating a new table, but why the whole three statements??? Actually we could create method without two of them, but so far as we determine id as primary key (I hope you know what these words mean) we have to provide unique id-values. There isn't auto_increment key-word in Oracle DB therefore to provide autoincrement of id-value for every new row in the table (and ensure unique id-values) we use another two statements.</p>
<p>We use "CREATE SEQUENCE" statement to create autoincrement per se. And we use "CREATE TRIGGER" statement to link operation of adding (inserting) new row to specified table with our sequence for id-field. As result when we insert new row we don't need to specify id-value, it'll be generated automatically.</p>
<p>By the way, don't duplicate my mistakes. Don't forget about semicolons in the TRIGGER statement.</p>
<h2>Fetch</h2>
<p>To fetch information from your table(es), type:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">java.sql.ResultSet</span><span class="o">;</span>
<span class="cm">/**</span>
<span class="cm"> * Executes query to OracleDB: fetch rows from database.</span>
<span class="cm"> * </span>
<span class="cm"> * @param connection</span>
<span class="cm"> * @param tablename</span>
<span class="cm"> * @return</span>
<span class="cm"> * @throws SQLException</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="n">ResultSet</span> <span class="nf">fetch</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">,</span> <span class="n">String</span> <span class="n">tablename</span><span class="o">)</span>
<span class="kd">throws</span> <span class="n">SQLException</span> <span class="o">{</span>
<span class="n">ResultSet</span> <span class="n">resultSet</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="n">Statement</span> <span class="n">statement</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="na">createStatement</span><span class="o">();</span>
<span class="n">resultSet</span> <span class="o">=</span> <span class="n">statement</span><span class="o">.</span><span class="na">executeQuery</span><span class="o">(</span><span class="s">"SELECT * FROM "</span> <span class="o">+</span> <span class="n">tablename</span><span class="o">);</span>
<span class="k">return</span> <span class="n">resultSet</span><span class="o">;</span>
<span class="o">}</span>
</pre></div>
<p>Here we're using executeQuery method because we don't change information, we only get it. This method returns instance of class ResultSet which includes all rows fetched by statement.</p>
<p>How can you get information from ResultSet instance? Very easy! See example:</p>
<div class="highlight"><pre><span class="cm">/**</span>
<span class="cm"> * Prints fetched data to console.</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">printFetched</span><span class="o">(</span><span class="n">ResultSet</span> <span class="n">resultSet</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">SQLException</span> <span class="o">{</span>
<span class="k">while</span> <span class="o">(</span><span class="n">resultSet</span><span class="o">.</span><span class="na">next</span><span class="o">())</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">id</span> <span class="o">=</span> <span class="n">resultSet</span><span class="o">.</span><span class="na">getString</span><span class="o">(</span><span class="s">"id"</span><span class="o">);</span>
<span class="n">String</span> <span class="n">title</span> <span class="o">=</span> <span class="n">resultSet</span><span class="o">.</span><span class="na">getString</span><span class="o">(</span><span class="s">"title"</span><span class="o">);</span>
<span class="kt">double</span> <span class="n">price</span> <span class="o">=</span> <span class="n">resultSet</span><span class="o">.</span><span class="na">getDouble</span><span class="o">(</span><span class="s">"price"</span><span class="o">);</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">id</span> <span class="o">+</span> <span class="s">"\t"</span> <span class="o">+</span> <span class="n">title</span> <span class="o">+</span> <span class="s">"\t"</span> <span class="o">+</span> <span class="n">price</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>ResultSet has get-methods not only for String and doulbe values, but for many others as well. Also this methods can receive interger arguments to get the <i>first</i> (1), <i>second</i> (2), <i>etc</i>. column. For instance you can change first getString method to:</p>
<div class="highlight"><pre><span class="n">String</span> <span class="n">id</span> <span class="o">=</span> <span class="n">resultSet</span><span class="o">.</span><span class="na">getString</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
</pre></div>
<h2>Insert</h2>
<p>If you launched previous method I think you got nothing. It's quite reasonable 'cause there are no rows in your table. To add new row to your table launch following:</p>
<div class="highlight"><pre><span class="cm">/**</span>
<span class="cm"> * Executes query to OracleDB: insert row to database.</span>
<span class="cm"> * </span>
<span class="cm"> * @param connection</span>
<span class="cm"> * @param tablename</span>
<span class="cm"> * @return</span>
<span class="cm"> * @throws SQLException</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">insert</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">,</span> <span class="n">String</span> <span class="n">tablename</span><span class="o">)</span>
<span class="kd">throws</span> <span class="n">SQLException</span> <span class="o">{</span>
<span class="n">Statement</span> <span class="n">statement</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="na">createStatement</span><span class="o">();</span>
<span class="n">statement</span><span class="o">.</span><span class="na">executeUpdate</span><span class="o">(</span><span class="s">"INSERT INTO "</span> <span class="o">+</span> <span class="n">tablename</span>
<span class="o">+</span> <span class="s">" (title, comments, price)"</span>
<span class="o">+</span> <span class="s">" VALUES('title', 'comment', '2')"</span><span class="o">);</span>
<span class="o">}</span>
</pre></div>
<p>After you executes this you'll get new record in your table. So printFetched() method won't print empty row-set :)</p>
<h2>Update</h2>
<p>To change specified rows you can use UPDATE statement:</p>
<div class="highlight"><pre><span class="cm">/**</span>
<span class="cm"> * Executes query to OracleDB: update row of table.</span>
<span class="cm"> * </span>
<span class="cm"> * @param connection</span>
<span class="cm"> * @param tablename</span>
<span class="cm"> * @return</span>
<span class="cm"> * @throws SQLException</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">update</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">,</span> <span class="n">String</span> <span class="n">tablename</span><span class="o">)</span>
<span class="kd">throws</span> <span class="n">SQLException</span> <span class="o">{</span>
<span class="n">Statement</span> <span class="n">statement</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="na">createStatement</span><span class="o">();</span>
<span class="n">statement</span><span class="o">.</span><span class="na">executeUpdate</span><span class="o">(</span><span class="s">"UPDATE "</span> <span class="o">+</span> <span class="n">tablename</span>
<span class="o">+</span> <span class="s">" SET title='title', comments='comment',"</span>
<span class="o">+</span> <span class="s">" price='2.7' WHERE id='3'"</span><span class="o">);</span>
<span class="o">}</span>
</pre></div>
<h2>Delete</h2>
<p>To delete specified rows use DELETE statement:</p>
<div class="highlight"><pre><span class="cm">/**</span>
<span class="cm"> * Executes query to OracleDB: delete row from table.</span>
<span class="cm"> * </span>
<span class="cm"> * @param connection</span>
<span class="cm"> * @param tablename</span>
<span class="cm"> * @return</span>
<span class="cm"> * @throws SQLException</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">delete</span><span class="o">(</span><span class="n">Connection</span> <span class="n">connection</span><span class="o">,</span> <span class="n">String</span> <span class="n">tablename</span><span class="o">)</span>
<span class="kd">throws</span> <span class="n">SQLException</span> <span class="o">{</span>
<span class="n">Statement</span> <span class="n">statement</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="na">createStatement</span><span class="o">();</span>
<span class="n">statement</span><span class="o">.</span><span class="na">executeUpdate</span><span class="o">(</span><span class="s">"DELETE FROM "</span> <span class="o">+</span> <span class="n">tablename</span> <span class="o">+</span> <span class="s">" WHERE id='1'"</span><span class="o">);</span>
<span class="o">}</span>
</pre></div>
<h2>Source Code</h2>
<p>You can get source code of this project <a href='http://sukharevd.net/static/files/blog/JDBC/jdbcManual.zip'>here</a></p>
<p>In archive is also class MySqlManager therefore you can get acquaint with JDBC for MySQL usage and compare MySqlManager and OracleDBManager classes.</p>