Recently I need to use 'Basic access authentication' with RestTemplate and most of resources pointed to org.springframework.http.client.CommonsClientHttpRequest as base for RestTemplate configuration. But I decided to switch from 'Commons HttpClient' to newer library provided again by Apache community: Apache HttpComponents. So having as example org.springframework.http.client.CommonsClient* classes I started to work and after 1-2 hours it was done. You can find sources here: source and here is small example how to use. First I created class with static factory method:
package info.sargis;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.springframework.http.client.ClientHttpRequestFactory;
import java.net.MalformedURLException;
import java.net.URL;
public class RequestFactoryManager {
public static ClientHttpRequestFactory createHttpClient(String service, String userName, String password) throws MalformedURLException {
URL serviceURL = new URL(service);
DefaultHttpClient httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager());
httpClient.getCredentialsProvider().setCredentials(
new AuthScope(serviceURL.getHost(), serviceURL.getPort()),
new UsernamePasswordCredentials(userName, password)
);
return new Commons2ClientHttpRequestFactory(httpClient);
}
}
and here is Spring XML config:
<bean id="clientHttpRequestFactory" class="info.sargis.RequestFactoryManager" factory-method="createHttpClient">
<constructor-arg value="${REST_SERVICE_URL}"/>
<constructor-arg value="${REST_USER_NAME}"/>
<constructor-arg value="${REST_USER_PASSWORD}"/>
</bean>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg ref="clientHttpRequestFactory"/>
<property name="messageConverters">
<list>
<bean class="info.sargis.AtomHttpMessageConverter"/>
<bean class="info.sargis.XMLStringHttpMessageConverter"/>
</list>
</property>
</bean>
And restTemplate bean ready to use :)
Tuesday, June 14, 2011
Friday, April 1, 2011
Fun with 'fluent interface' and Java
Here is my story about 'fluent interface' and Java. In one project I have to compare in many places BigDecimals and other Comparable objects. So if I have:
In Java to compare BigDecimals I should use
if(requestedAmount.compareTo(paymentAmount) == 0) {
}
For me its not natural to compare numbers in such way and I decided to try to write small technical DSL, and here how looks my code now:
import static com.webbfontaine.twm.accounting.epaylog.utils.CompareDSL.*;
if (eq(valueOf(paymentAmount).comparingWith(requestedAmount))) {
}
and here is API/DSL code:
BigDecimal requestedAmount = ...
BigDecimal paymentAmount = ...
In Java to compare BigDecimals I should use
if(requestedAmount.compareTo(paymentAmount) == 0) {
}
For me its not natural to compare numbers in such way and I decided to try to write small technical DSL, and here how looks my code now:
import static com.webbfontaine.twm.accounting.epaylog.utils.CompareDSL.*;
if (eq(valueOf(paymentAmount).comparingWith(requestedAmount))) {
}
if (ne(valueOf(paymentAmount).comparingWith(requestedAmount))) {
}
if (gt(valueOf(paymentAmount).comparingWith(requestedAmount))) {
}
.... and etc.
and here is API/DSL code:
public class CompareDSL {
public static <T extends Comparable<T>> PairToCompare<T> valueOf(T value) {
return new PairToCompare<T>(value);
}
public static <T extends Comparable<T>> boolean eq(PairToCompare<T> pairToCompare) {
return pairToCompare.firstValue.compareTo(pairToCompare.secondValue) == 0;
}
public static <T extends Comparable<T>> boolean ne(PairToCompare<T> pairToCompare) {
return !eq(pairToCompare);
}
public static <T extends Comparable<T>> boolean gt(PairToCompare<T> pairToCompare) {
return pairToCompare.firstValue.compareTo(pairToCompare.secondValue) > 0;
}
public static <T extends Comparable<T>> boolean ge(PairToCompare<T> pairToCompare) {
return pairToCompare.firstValue.compareTo(pairToCompare.secondValue) >= 0;
}
public static <T extends Comparable<T>> boolean lt(PairToCompare<T> pairToCompare) {
return pairToCompare.firstValue.compareTo(pairToCompare.secondValue) < 0;
}
public static <T extends Comparable<T>> boolean le(PairToCompare<T> pairToCompare) {
return pairToCompare.firstValue.compareTo(pairToCompare.secondValue) <= 0;
}
public static class PairToCompare<T extends Comparable<T>> {
private T firstValue;
private T secondValue;
public PairToCompare(T firstValue) {
this.firstValue = firstValue;
}
public PairToCompare<T> comparingWith(T value) {
this.secondValue = value;
return this;
}
}
}
API of course not the best one, but for me it works fine and it was fun to write it :-)
API of course not the best one, but for me it works fine and it was fun to write it :-)
Thursday, March 24, 2011
Wednesday, November 3, 2010
Start and stop VMware virtual machine as service for Linux OS
Here is my simple script for starting(non gui mode) automatically VMWare guests on system startup
[sargis@appsrv ~]# cat /etc/init.d/vm-guests
#!/bin/bash
#
# chkconfig: 235 81 29
# description: Start vmware guests.
# Source function library.
. /etc/rc.d/init.d/functions
case "$1" in
start)
echo -n $"Starting vmware guests: "
su - sargis -c "/usr/bin/vmrun -T ws start /srv/vmware/ dsrv/ dsrv.vmx nogui"
echo
;;
stop)
echo -n $"Shutting down vmware guests: "
/usr/bin/vmrun -T ws stop /srv/vmware/dsrv/ dsrv.vmx
echo
;;
restart|force-reload)
stop
start
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 2
esac
[sargis@appsrv ~]# cat /etc/init.d/vm-guests
#!/bin/bash
#
# chkconfig: 235 81 29
# description: Start vmware guests.
# Source function library.
. /etc/rc.d/init.d/functions
case "$1" in
start)
echo -n $"Starting vmware guests: "
su - sargis -c "/usr/bin/vmrun -T ws start /srv/vmware/
echo
;;
stop)
echo -n $"Shutting down vmware guests: "
/usr/bin/vmrun -T ws stop /srv/vmware/dsrv/
echo
;;
restart|force-reload)
stop
start
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 2
esac
Sunday, October 17, 2010
How to configure Oracle/SUN JVM to send notification in case of JVM fatal error/crash
Recently we had JVM crash in production server and of course we had notified by some monitoring tools but not as fast as we could expect. So I configured our server with following JVM option:
-XX:OnError="sendjvmcrashsms". 'sendjvmcrashsms' is a Linux shell/bash file which is of course in user PATH, and here is example of the file
#! /bin/bash
echo "Production JVM crashed" | mail -s "+33000000000"
It will send mail to address with subject '+33000000000'. In our server we have configured SMS gateway which will send SMS to number(s) defined in subject, and here is docs:
-XX:OnError="<cmd args>;<cmd args>" - Run user-defined commands on fatal error
-XX:OnError="sendjvmcrashsms". 'sendjvmcrashsms' is a Linux shell/bash file which is of course in user PATH, and here is example of the file
#! /bin/bash
echo "Production JVM crashed" | mail -s "+33000000000"
It will send mail to address
-XX:OnError="
Sunday, October 10, 2010
Experience with slf4j/logback markers
I want to share my experience with slf4j/logback markers, hope can be useful for others.
Problem: want to have possibility to mail for particular log messages regardless log level.
Solution: Using slf4j/logback markers to mark :) interested messages and logback Filter.
First I've defined simple class to keep like global registry for slf4j markers:
public class LOGMarkers {
public static final Marker SEND_MAIL_MARKER = MarkerFactory.getMarker("SEND_MAIL");
}
and here is code example which is actually using marker:
LOGGER.info(LOGMarkers.SEND_MAIL_MARKER, "Cannot save document with id: {}", instanceId);
or
try {
.................
} catch (SomeException e) {
LOGGER.warn(LOGMarkers.SEND_MAIL_MARKER, "", e);
}
also I have to write logback filters and use it in logback configuration file:
package info.sargis.logging.filter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.AbstractMatcherFilter;
import ch.qos.logback.core.spi.FilterReply;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
/**
* Created by IntelliJ IDEA.
* User: Sargis Harutyunyan
* Date: 10 oct. 2010
* Time: 20:12:12
*/
public class MarkerFilter extends AbstractMatcherFilter {
Marker markerToMatch;
public void start() {
if (this.markerToMatch != null) {
super.start();
} else {
addError(String.format("The marker property must be set for [%s]", getName()));
}
}
public FilterReply decide(ILoggingEvent event) {
Marker marker = event.getMarker();
if (!isStarted()) {
return FilterReply.NEUTRAL;
}
if (marker == null) {
return onMismatch;
}
if (markerToMatch.contains(marker)) {
return onMatch;
}
return onMismatch;
}
public void setMarker(String markerStr) {
if (markerStr != null) {
markerToMatch = MarkerFactory.getMarker(markerStr);
}
}
}
and finally logback config file example:
<appender name="MARKER_EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
<filter class="info.sargis.logging.filter.MarkerFilter">
<marker>SEND_MAIL</marker>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
<marker>SEND_MAIL</marker>
</evaluator>
<SMTPHost>localhost</SMTPHost>
<To>sargis@localhost</To>
<From>twm@localhost</From>
<Subject>EPAYMAIL: %date %-5level - %message</Subject>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%date [%thread] %-5level U:%X{vaspId} - %message%n</Pattern>
</layout>
</appender>
<logger name="info.sargis" level="INFO">
<appender-ref ref="EPAYCONSOLE"/>
<appender-ref ref="MARKER_EMAIL"/>
</logger>
and voila :)
Problem: want to have possibility to mail for particular log messages regardless log level.
Solution: Using slf4j/logback markers to mark :) interested messages and logback Filter.
First I've defined simple class to keep like global registry for slf4j markers:
public class LOGMarkers {
public static final Marker SEND_MAIL_MARKER = MarkerFactory.getMarker("SEND_MAIL");
}
and here is code example which is actually using marker:
LOGGER.info(LOGMarkers.SEND_MAIL_MARKER, "Cannot save document with id: {}", instanceId);
or
try {
.................
} catch (SomeException e) {
LOGGER.warn(LOGMarkers.SEND_MAIL_MARKER, "", e);
}
also I have to write logback filters and use it in logback configuration file:
package info.sargis.logging.filter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.AbstractMatcherFilter;
import ch.qos.logback.core.spi.FilterReply;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
/**
* Created by IntelliJ IDEA.
* User: Sargis Harutyunyan
* Date: 10 oct. 2010
* Time: 20:12:12
*/
public class MarkerFilter extends AbstractMatcherFilter
Marker markerToMatch;
public void start() {
if (this.markerToMatch != null) {
}
public FilterReply decide(ILoggingEvent event) {
Marker marker = event.getMarker();
if (!isStarted()) {
if (marker == null) {
if (markerToMatch.contains(marker)) {
return onMismatch;
}
public void setMarker(String markerStr) {
if (markerStr != null) {
}
}
and finally logback config file example:
<appender name="MARKER_EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
<filter class="info.sargis.logging.filter.MarkerFilter">
<marker>SEND_MAIL</marker>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
<marker>SEND_MAIL</marker>
</evaluator>
<SMTPHost>localhost</SMTPHost>
<To>sargis@localhost</To>
<From>twm@localhost</From>
<Subject>EPAYMAIL: %date %-5level - %message</Subject>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%date [%thread] %-5level U:%X{vaspId} - %message%n</Pattern>
</layout>
</appender>
<logger name="info.sargis" level="INFO">
<appender-ref ref="EPAYCONSOLE"/>
<appender-ref ref="MARKER_EMAIL"/>
</logger>
Thursday, August 26, 2010
SVN, Sparse Directories, Now With Exclusion
Sparse Directories, Now With Exclusion
If I had a dollar for every time I've typed that… well, you and I could at least spring for some Fazoli's fast-food Italian. Okay, I admit that the emotion doesn't always drive me to public expression, but that in no way diminishes my fondness for this feature.
Introduced in Subversion 1.5, sparse directory support is one of a few features from that release (besides merge tracking and foreign repository merges) that I've fully integrated into my day-to-day activities. I dig organization. I tend to keep a pretty neat home directory. But I routinely work on several different pieces of software, and at any given time, I'm tracking several different development branches in each of those pieces of software. Were I not using sparse directories, my "projects" directory would look something like this:
$ ls ~/projects
subversion/ svnbook/ viewvc-1.0.7/
subversion-1.5.x/ thotkeeper/ viewvc-1.0.x/
subversion-1.6.x/ thotkeeper-0.3.0/ viewvc-1.1.0-beta1/
subversion-http-protocol-v2/ viewvc/ viewvc-1.1.x/
$
On the positive side of things, I could quickly update all my working copies by simply running svn update ~/projects/*.
But those of you who have command-line completion as hard-wired into your habits as I do will immediately notice that so many common directory prefixes does a useless completion environment make. And not using common prefixes? Well that's just barbaric.
Fortunately, sparse directories has given me a whole new perspective on working copy organization. Now, my projects directory contains (gasp!) only projects, and looks like this:
$ ls ~/projects
subversion/ svnbook/ thotkeeper/ viewvc/
$
Those directories are sparse checkouts of the root directories of their respective project repositories. Beneath them are (at least) "trunk" directories, probably "branch" and some of its children, and maybe even "tags" with some of its children in certain cases. svn up ~/projects/* still works, and my working copy topology matches that of the repositories.
I won't go into the details of how sparse checkouts works here — I've already documented the Subversion 1.5 implementation of them in the second edition of Version Control With Subversion (which you can read at http://svnbook.red-bean.com/en/1.5/svn.advanced.sparsedirs.html). The point of this blog post is to tell you about how Subversion 1.6 improves this feature in a key way.
In Subversion 1.6 (slated for release Any Day Now), the --set-depth parameter to svn update has grown a new value — exclude. This value tells Subversion to exclude the target from the working copy, immediately and until further notice. Prior to Subversion 1.6, if a branch I was working on was no longer of interest to me, I couldn't easily remove it from my working copy. If I simply deleted it, it would return the next time I updated the working copy. If I svn delete'd it, the branch remained as a local modification forever. (Unless, of course, I accidentally committed it, which brought a whole different sort of trouble to my doorstep. Angry peers. Pitchforks and torches. It was a mess — you don't want to go there.) The new exclusion mechanism in Subversion 1.6 is the Right Way To Do It.
Say I no longer care about what's going on some directory of one my project working copies. Maybe I don't care about the Subversion project's website any more. Well, with this new exclusion feature, I can tell Subversion to remove that directory:
$ cd ~/projects/subversion/trunk
$ svn update --set-depth=exclude www
D www
$ ls www
ls: cannot access www: No such file or directory
$
Done deal. When I update my working copy in the future, I will not receive any changes aimed at that www directory. If I later decide that I once again care about that directory, I can "resubscribe" to it again:
$ svn update --set-depth=infinity www
A www
A www/links.html
A www/testing-goals.html
…
A www/tigris-permissions.html
A www/webdav-usage.html
Updated to revision 36292.
$
Note that if you exclude a versioned directory that has some unversioned files in it, or some files with local modifications, Subversion handles this situation gracefully. All the files that aren't safe to delete, Subversion leaves around, and of course leaves any intermediate directories required to reach those files, too.
I hope this enhancement serves you as well as it has served me. What do you think? How are you using sparse directories to better organize your life?
If I had a dollar for every time I've typed that… well, you and I could at least spring for some Fazoli's fast-food Italian. Okay, I admit that the emotion doesn't always drive me to public expression, but that in no way diminishes my fondness for this feature.
Introduced in Subversion 1.5, sparse directory support is one of a few features from that release (besides merge tracking and foreign repository merges) that I've fully integrated into my day-to-day activities. I dig organization. I tend to keep a pretty neat home directory. But I routinely work on several different pieces of software, and at any given time, I'm tracking several different development branches in each of those pieces of software. Were I not using sparse directories, my "projects" directory would look something like this:
$ ls ~/projects
subversion/ svnbook/ viewvc-1.0.7/
subversion-1.5.x/ thotkeeper/ viewvc-1.0.x/
subversion-1.6.x/ thotkeeper-0.3.0/ viewvc-1.1.0-beta1/
subversion-http-protocol-v2/ viewvc/ viewvc-1.1.x/
$
On the positive side of things, I could quickly update all my working copies by simply running svn update ~/projects/*.
But those of you who have command-line completion as hard-wired into your habits as I do will immediately notice that so many common directory prefixes does a useless completion environment make. And not using common prefixes? Well that's just barbaric.
Fortunately, sparse directories has given me a whole new perspective on working copy organization. Now, my projects directory contains (gasp!) only projects, and looks like this:
$ ls ~/projects
subversion/ svnbook/ thotkeeper/ viewvc/
$
Those directories are sparse checkouts of the root directories of their respective project repositories. Beneath them are (at least) "trunk" directories, probably "branch" and some of its children, and maybe even "tags" with some of its children in certain cases. svn up ~/projects/* still works, and my working copy topology matches that of the repositories.
I won't go into the details of how sparse checkouts works here — I've already documented the Subversion 1.5 implementation of them in the second edition of Version Control With Subversion (which you can read at http://svnbook.red-bean.com/en/1.5/svn.advanced.sparsedirs.html). The point of this blog post is to tell you about how Subversion 1.6 improves this feature in a key way.
In Subversion 1.6 (slated for release Any Day Now), the --set-depth parameter to svn update has grown a new value — exclude. This value tells Subversion to exclude the target from the working copy, immediately and until further notice. Prior to Subversion 1.6, if a branch I was working on was no longer of interest to me, I couldn't easily remove it from my working copy. If I simply deleted it, it would return the next time I updated the working copy. If I svn delete'd it, the branch remained as a local modification forever. (Unless, of course, I accidentally committed it, which brought a whole different sort of trouble to my doorstep. Angry peers. Pitchforks and torches. It was a mess — you don't want to go there.) The new exclusion mechanism in Subversion 1.6 is the Right Way To Do It.
Say I no longer care about what's going on some directory of one my project working copies. Maybe I don't care about the Subversion project's website any more. Well, with this new exclusion feature, I can tell Subversion to remove that directory:
$ cd ~/projects/subversion/trunk
$ svn update --set-depth=exclude www
D www
$ ls www
ls: cannot access www: No such file or directory
$
Done deal. When I update my working copy in the future, I will not receive any changes aimed at that www directory. If I later decide that I once again care about that directory, I can "resubscribe" to it again:
$ svn update --set-depth=infinity www
A www
A www/links.html
A www/testing-goals.html
…
A www/tigris-permissions.html
A www/webdav-usage.html
Updated to revision 36292.
$
Note that if you exclude a versioned directory that has some unversioned files in it, or some files with local modifications, Subversion handles this situation gracefully. All the files that aren't safe to delete, Subversion leaves around, and of course leaves any intermediate directories required to reach those files, too.
I hope this enhancement serves you as well as it has served me. What do you think? How are you using sparse directories to better organize your life?
Subscribe to:
Posts (Atom)