Hi, I need to get current method in java, one solution is of course using Thread.currentThread().getStackTrace() but its not portable because: Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. So I used following solution, not so good but works
public void testMethod() {
Method currentMethod = new MethodHelper() {
@Override
public Method getCurrentMethod() {
return getClass().getEnclosingMethod();
}
}.getCurrentMethod();
...................................
}
and
public interface MethodHelper {
Method getCurrentMethod();
}
PS: please read getEnclosingMethod() JavaDoc it can return null as well.
"Java" :: "Scala" :: "Groovy" :: "Ruby" :: "and other stuff :)" :: Nil
Sargis Harutyunyan
Tuesday, August 9, 2011
Saturday, June 25, 2011
ActiveMQ messages database logging with Apache Camel
Hi, we had epayment system based on Fuse ActiveMQ and we decided to log into DB all messages passed through ActiveMQ. I want to share my first experience with Apache Camel :)
I changed ActiveMQ configuration and used ActiveMQ feature: 'Mirrored Queues' to forward all messages to mirrored queues prefixed with qmirror. Here is ActiceMQ configuration:
<destinationInterceptors>
<mirroredQueue copyMessage = "true" postfix="" prefix="qmirror."/>
</destinationInterceptors>
So now when we have copied messages in queues with names: 'qmirror.*' and it is time to log them with Apache Camel. Thus I changed '$ACTIVEMQ_HOME/conf/camel.xml' config file in the following way:
|-- docs
| `-- create_db.sql
|-- payment-dblogger.iml
|-- pom.xml
|-- README.txt
`-- src
|-- data
`-- main
|-- java
| `-- info
| `-- sargis
| `-- dbloggger
| |-- DBLoggerRouteBuilder.java
| `-- logger
| |-- DBLogger.java
| |-- DBLoggerProcessor.java
| `-- Logger.java
`-- resources
|-- log4j.properties
`-- META-INF
`-- spring
`-- camel-context.xml
note that project artifact payment-dblogger-*.jar should be deployed to '$ACTIVEMQ_HOME/webapps/camel/WEB-INF/lib'
Now its time for router :) here everything is simple as well:
package info.sargis.dbloggger;
import org.apache.camel.builder.RouteBuilder;
public class DBLoggerRouteBuilder extends RouteBuilder {
@Override
public void configure() {
from("activemq:topic:qmirror.>").threads().processRef("dbLoggerProcessor");
}
}
I changed ActiveMQ configuration and used ActiveMQ feature: 'Mirrored Queues' to forward all messages to mirrored queues prefixed with qmirror. Here is ActiceMQ configuration:
<destinationInterceptors>
<mirroredQueue copyMessage = "true" postfix="" prefix="qmirror."/>
</destinationInterceptors>
So now when we have copied messages in queues with names: 'qmirror.*' and it is time to log them with Apache Camel. Thus I changed '$ACTIVEMQ_HOME/conf/camel.xml' config file in the following way:
<beans...>
<context:component-scan base-package="info.sargis.dbloggger"/>
<context:annotation-config/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<package>info.sargis.dbloggger</package>
</camelContext>
<bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:TWMDB"/>
<property name="username" value="activemq"/>
<property name="password" value="ee0thaXu"/>
<property name="maxActive" value="5"/>
<property name="maxIdle" value="2"/>
</bean>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL"
value="vm://localhost?create=false&waitForStart=10000&broker.populateJMSXUserID=true"/>
<property name="userName" value="${activemq.username}"/>
<property name="password" value="${activemq.password}"/>
</bean>
</property>
</bean>
</beans>
and created project with structure:
| `-- create_db.sql
|-- payment-dblogger.iml
|-- pom.xml
|-- README.txt
`-- src
|-- data
`-- main
|-- java
| `-- info
| `-- sargis
| `-- dbloggger
| |-- DBLoggerRouteBuilder.java
| `-- logger
| |-- DBLogger.java
| |-- DBLoggerProcessor.java
| `-- Logger.java
`-- resources
|-- log4j.properties
`-- META-INF
`-- spring
`-- camel-context.xml
note that project artifact payment-dblogger-*.jar should be deployed to '$ACTIVEMQ_HOME/webapps/camel/WEB-INF/lib'
Now its time for router :) here everything is simple as well:
package info.sargis.dbloggger;
import org.apache.camel.builder.RouteBuilder;
public class DBLoggerRouteBuilder extends RouteBuilder {
@Override
public void configure() {
from("activemq:topic:qmirror.>").threads().processRef("dbLoggerProcessor");
}
}
Tuesday, June 14, 2011
Spring RestTemplate integration with HttpComponents Client
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 :)
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 :)
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="
Subscribe to:
Posts (Atom)