Wednesday, February 12, 2014

Upload file with SCP

linux command scp is tool for uploading files over ssh. For simple uploading file from local file to remote host could be used this:

scp ~/Downloads/apache-tomcat-7.0.50.tar.gz karel@123.17.131.12:/home/karel/

Previous command will upload apache tomcat install file from local Download directory to remote home of user karel. User will be asked for karel's password.

Than login to remote server as user karel and finally extract apache server in a following way:

tar -zxvf apache-tomcat-7.0.50.tar.gz

And it's done.

Monday, February 10, 2014

Camel error - No component found with scheme: stream

During Camel startup I found following exception:

2014-02-10 09:18:51 - Context initialization failed
org.apache.camel.RuntimeCamelException: org.apache.camel.FailedToCreateRouteException: Failed to create route route1 at: >>> To[stream:out] <<< in route: Route(route1)[[From[file:src/data?noop=true]] -> [ConvertBod... because of Failed to resolve endpoint: stream://out due to: No component found with scheme: stream

The problem is in missing dependency to library that contains stream:out endpoint. In maven it should look like:

<dependency>
 <groupId>org.apache.camel</groupId>
 <artifactId>camel-stream</artifactId>
 <version>${camel-version}</version>
</dependency>

Value of camel-version should be same as camel-core version.

Friday, December 6, 2013

DbUnit WARN in logs "Extra columns on line 2. Those columns will be ignored."

WARN dbunit.dataset.xml.FlatXmlProducer - Extra columns on line 2.  Those columns will be ignored.
WARN dbunit.dataset.xml.FlatXmlProducer - Please add the extra columns to line 1, or use a DTD to make sure the value of those columns are populated or specify 'columnSensing=true' for your FlatXmlProducer.
WARN dbunit.dataset.xml.FlatXmlProducer - See FAQ for more details.

Problem was in XML file which defined data that should be loaded to database. Here is simplified version:

 <user id_user="1"/>

 <user id_user="2" login="john" />

Problem was in parameter columnSensing. During reading XML data with FlatXmlProducer parameter columnSensing was defined as false or wasn't defined which is treated as false. Let's look at meaning of columnSensing parameter.

This parameter define which columns will be inserted into tables. When parameter columnSensing is falseDbUnit reads xml elements defining data one by one. When new element is detected that all attribute are considered as column names. Next time when element with same name is found inserted into database table are just already columns. When columnSensing is true than columns will be inserted into database table even if they are not defined in first XML element.

Solution 1.

First solution of previous example is quite easy just set columnSensing parameter to true.

Solution 2.

It's also really straightforward reorder XML elements:

 <user id_user="2" login="john" />

 <user id_user="1"/>

Solution 3.

In more complex XML files previous solutions can't be used, so define in first XML element as null. So it should like this:

 <user id_user="1" login ="[NULL]"/>

 <user id_user="2" login="john" />

DbUnit doesn't understand null value as null value. There have to be piece of code that learn DbUnit [NULL] value:

IDataSet dataSet = new FlatXmlDataSet(new FileInputStream("dataset.xml"));
ReplacementDataSet finalDataSet = new ReplacementDataSet(dataSet);
finalDataSet.addReplacementObject("[NULL]", null);

I don't know if it's DbUnit error or some misinterpretation of my XML file but DbUnit detect problem at line 1 or 2 even if real problem occurs many lines after.

Thursday, December 5, 2013

guava Files - unable to delete temporaly directory

I had strange problem on my Mac. Following code:
File indexBaseFile = com.google.common.io.Files.createTempDir();

... some creating of files inside directory

Files.deleteRecursively(indexBaseFile);
always ends with following exception:
java.io.IOException: Failed to delete /var/folders/c5/j25r9j1j1jx_t4wzrzmf53300000gn/T/1386264920188-0
 at com.google.common.io.Files.deleteRecursively(Files.java:537)
The trick is that guava library before deleting file check that deleted file is not a symbolic link. On Mac /var is pointing to /private/var. So now to fix this problem was easy:
File indexBaseFile = com.google.common.io.Files.createTempDir().getAbsolutePath();

... some creating of files inside directory

Files.deleteRecursively(indexBaseFile);
There is extra .getAbsolutePath() calling. This method return absolute path with resolved symbolic links.

Tapestry 5 Invalid configuration

I met following configuration exception in logs:
Caused by: java.lang.IllegalArgumentException: Service 'ChangeLogProcessor' is configured using 
org.apache.tapestry5.ioc.OrderedConfiguration, not org.apache.tapestry5.ioc.Configuration.
 at org.apache.tapestry5.ioc.internal.util.WrongConfigurationTypeGuard.findResource(WrongConfigurationTypeGuard.java:40)
 at org.apache.tapestry5.ioc.internal.util.DelegatingInjectionResources.findResource(DelegatingInjectionResources.java:36)
 at org.apache.tapestry5.ioc.internal.util.DelegatingInjectionResources.findResource(DelegatingInjectionResources.java:38)

Problem was related to Tapestry 5 chain of commands builder. It's Tapestry 5 build-in service that helps to implement that design pattern. My chain of commands definition was:
public static ChangeLogProcessor buildChangeLogProcessor(List<ChangeLogProcessor> commands,
    @InjectService("ChainBuilder") ChainBuilder chainBuilder) {
    return chainBuilder.build(ChangeLogProcessor.class, commands);
}

public static void contributeChangeLogProcessor(
    final Configuration<ChangeLogProcessor> configuration,
    final @Autobuild ChangeLogBoxProcessor changeLogBoxProcessor) {
    configuration.add(changeLogBoxProcessor);
}
After some time I found that problem was in contribute method, in build method is configuration defined as List which should be in contribute method defined as OrderedConfiguration not as Configuration. So following corrected code works fine:
public static void contributeChangeLogProcessor(
    final OrderedConfiguration<ChangeLogProcessor> configuration,
    final @Autobuild ChangeLogBoxProcessor changeLogBoxProcessor) {
    configuration.add("boxProcessor", changeLogBoxProcessor);
}

Monday, November 4, 2013

Apache HTTPD and Tomcat configuration

I run some application at linux server. It's quite simple installation but sometimes it's difficult for me to remember why it's configure in such way. This post helps me to understand current state. Hopefully it will be useful for someone else.
Server is just one linux box with CentOS. There are no dependencies to other nodes or services. It's really simple.
On server is installed Apache HTTPD service. Service could be started stopped via commands /etc/init.d/https {stop|start| ...}. Among others apache contains module mod_jk which is responsible for communication with AJP protocol load balancing and other stuff. Closer description of mod_jk could be found at http://tomcat.apache.org/connectors-doc/. The reason why I need Apache HTTPS in front of Tomcat server is that I need more tomcats for different hosted domains and Apache HTTPD server is used also for PHP. Connection between Apache HTTPD server and Tomcat servers is at following image.
Applications are also split between few linux system accounts. It's because of security.
Now let's look at configuration of Apache HTTPD:

<VirtualHost *:80>
   ServerName www.domain2.com 
   ServerAlias *.domain2.com
   ServerAlias *.domain3.com
   ErrorLog /var/log/httpd/domain2.com.err.log
   CustomLog /var/log/httpd/domain2.com.log combined

   <Proxy *>
     AddDefaultCharset Off
     Order deny,allow
     Allow from all
   </Proxy>
 
   ProxyPass / ajp://localhost:7001/
   ProxyPassReverse / ajp://localhost:7001/
</VirtualHost>


<VirtualHost *:80>
   ServerName www.domain1.com
   ServerAlias *domain1.com
   ErrorLog /var/log/httpd/domain1.com.err.log
   CustomLog /var/log/httpd/domain1.com.log combined

   <Proxy *>
     AddDefaultCharset Off
     Order deny,allow
     Allow from all
   </Proxy>
 
   ProxyPass / ajp://localhost:7005/
   ProxyPassReverse / ajp://localhost:7005/
</VirtualHost>
Finally there have to be some configuration at Tomcats side. Here is configuration from tomcat2 ./conf/server.xml file:
<Connector port="7001" protocol="AJP/1.3" redirectPort="8443" />

<Engine name="Catalina" defaultHost="www.domain2.com">

<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>

    <Host name="repo.domain2" appBase="domain/repo.domain2.com"
        unpackWARs="true" autoDeploy="true"
        xmlValidation="false" xmlNamespaceAware="false">
    </Host>

    <Host name="www.domain2.com" appBase="domain/www.domain2.com"
        unpackWARs="true" autoDeploy="true"
        xmlValidation="false" xmlNamespaceAware="false">
        <Alias>domain2.com</Alias>
    </Host>

    <Host name="www.domain3.com" appBase="domain/www.domain3.com"
        unpackWARs="true" autoDeploy="true"
        xmlValidation="false" xmlNamespaceAware="false">
        <Alias>domain2.com</Alias>
    </Host>

</Engine>

curl - GET single file

Curl is simple yet powerful tool for creating HTTP and FTP requests of all kind. I have permanent problem with simple getting file with curl and storing in to file system. This little post should remember it to me. Basically works like this:
curl -v --location --max-redirs 10 \
 --output install_1.3.0.sql \
 http://somesite.com/somefile.sql
One trick is to use --location which tell to curl to follow redirects until number of redirect reach value specified in --max-redirs. Second trick is to specify output file in --output. When output file is not specified retrieved data are send to console (STDOUT).