Friday, November 23, 2012

An excellent solution for local dependencies with Maven projects

I found this tip on Heroku devcenter website.

https://devcenter.heroku.com/articles/local-maven-dependencies

In a few words, you add a "repo" directory to your project, deploy your artifact into this local repo and declare this repository in your pom.xml. Then, you can use your local jar as classic maven dependency.

Here is the example :

yourproject
+- pom.xml
+- src
+- repo
mvn deploy:deploy-file -Durl=file:///path/to/yourproject/repo/ -Dfile=mylib-1.0.jar -DgroupId=com.example -DartifactId=mylib -Dpackaging=jar -Dversion=1.0
It's just perfect! Thanks to the Heroku member who had this excellent idea!














Thursday, October 18, 2012

A solution to have environment specific Spring application context files

I found this post today : http://www.drillio.com/en/software-development/spring/context-bootstrapping-with-different-environment-configurations/
 
I have the following problem : I need to customize a web application. For example, on a production environment, I want my app to be automatically configured with production parameters. As this application uses Spring namespaces (grrrr), I can't use a DefaultPropertyPlaceHolderConfigurer to inject properties dynamically into config files. I really need to have Spring conf files per environment.

I made some changes to the code to make it compatible with Spring 2.5.6. Here are my classes :


https://sites.google.com/site/javacolorsfiles/SpringContextBootstrapper.java
https://sites.google.com/site/javacolorsfiles/ConfigLocationProviderImpl.java
https://sites.google.com/site/javacolorsfiles/ConfigLocationProvider.java

And an example of Spring conf behind :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
                http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <bean name="bootstrap" class="com.essec.spring.extension.bootstrapper.SpringContextBootstrapper" init-method="init">
        <property name="configLocations">
            <list>
                <value>classpath:applicationContext.xml</value>
            </list>
        </property>
    </bean>

    <!-- and this is a modified content from one of our live applications -->
    <bean class="com.essec.spring.extension.bootstrapper.ConfigLocationProviderImpl">
        <property name="configLocations">
            <list>
                <!-- here comes our dynamic config location -->
                <value>classpath:${spring.applicationContext}</value>
            </list>
        </property>
    </bean>

</beans>

Wednesday, September 26, 2012

How to install Python 2.7.2 on RedHat Enterprise Linux 5.2

Want you install Python 2.7 to run a Google App Engine server on your old RHEL 5.2? I can just say that it was impossible for me from the sources. Hopefully, I find a excellent blog post which gives an alternative install script. Just download and run it. It will download and install Python 2.7.2 and its commons dependencies. The only limit I know is that you cannot Python based apps with GUIs because it's not compiled against TCL/TK.

http://rajaseelan.com/2012/01/28/installing-python-2-dot-7-2-on-centos-5-dot-2/

Thursday, August 02, 2012

How to disable scrollbars overlay on Ubuntu 12.04

Just open a terminal and execute the following command :
  • gsettings set org.gnome.desktop.interface ubuntu-overlay-scrollbars false
Enjoy the difference!

Wednesday, July 04, 2012

JRebel free alternatives

I'm a daily user of JRebel. JRebel allows you to program in Java like in PHP. It means that you don't need to restart your application to see your changes because JRebel perfoms hot code replace.

Even if it's a fantastic product, I wanted to see if I could integrate such a feature in an open source project I'm working on (tomcat-lsd). And I found these projects :

  • dcevm : http://ssw.jku.at/dcevm
  • FakeReplace : https://github.com/fakereplace
  • Apache common jci fam : http://commons.apache.org/jci/commons-jci-fam/index.html
  • Agent Smith : http://java.net/projects/agentsmith
Of course, JRebel is still more powerfull than these projects but I think they are two very good intiatives.

PS : after some other goolings, I found a blog dedicated to class reloading : http://classreloadingwebapp.blogspot.com/  . Many thanks to its author and his great post on jci.

Monday, June 04, 2012

Install a network printer from Ubuntu 12.04 with Gnome Shell

If you try to install a network printer from Ubuntu 12.04 with Gnome shell, you will probably have an error message like "Firewalld is not started". There is a workaround you can use. Press Alt+F2 and type system-config-printer.

Tuesday, May 29, 2012

How to register SSL certificates in your JVM?

You wrote a Java program which needs to access to a external ressource through SSL (such as LDAPS or HTTPS)?

Okay, this post is for you.

The first thing you have to know is that the first time you established a secured connection to something, you (normally) have to accept the certificate used to encrypt the dialog. In apps with interaction with end users (such as a web browser), the user often see a popup which asks him to trust the certificate. But, if the secured connection is establised behind the scene  (without any possibility to show a popup to somebody, such in batch process apps), the certificate must be trusted before establishing the connection.

In Java, there's a wallet which contains trusted certificate. It is located in [JAVA_HOME]/jre/lib/security/cacerts

I explain here how to extract the public key of a SSL certificate and how to register is in the cacerts file.

Step 1 : let's extract the public key from a secured connection


We will use OpenSSL for that. Just run from a shell :
openssl s_client -connect [URL_TO_REACH]:443 > cert.pem

This will generate a file "cert.pem". Edit this file and remove the text before and after the certificate (You will understand while you will see it)

Step 2 : register the cert.pem in the cacerts wallet


There are four prerequisites to know :
  • the certificate has to be associated with a n alias in the wallet (and you will see that you will be able to remove it from the wallet by this alias later)
  • for unix users, you have to be root to register a certificate
  • the default password of the cacerts wallet is "changeit"
  • don't forget to restart your program after having registered the certificate
 To register your cert.pem, just do :
su -c "[JAVA_HOME]/jre/bin/keytool -import -alias [MY_CERT_ALIAS] -keypass changeit -keystore [JAVA_HOME]/jre/lib/security/cacerts -file cert.pem"
(Don't forget to replace [JAVA_HOME] and [MY_CERT_ALIAS] with your own values.

If you need to remove this certificate, just do :
su -c "[JAVA_HOME]/jre/bin/keytool -delete -alias [MY_CERT_ALIAS] -keypass changeit -keystore [JAVA_HOME]/jre/lib/security/cacerts"

That's all.

UPDATE (October 2016) : 


If you have an handshake failure, try this :

openssl s_client -tls1 -connect [URL_TO_REACH]:443 > cert.pem

Friday, April 06, 2012

Inject constants in bean fields with Spring 3.0

Today, I imported some properties in my Spring config file. I wrote something like this :

<!-- define properties from a file -->
<util:properties id="securityProperties"  location="classpath:/securityProperties.properties" />

I could also wrote :

<!-- look for properties from a JNDI context -->
<jee:jndi-lookup id="securityProperties" jndi-name="props/security" />

... or even more simpler :

<!-- simply declare properties directly -->
<util:properties id="securityConstant">
    <prop key="cas.base.url">blablabla</prop>
</util:properties>

So, I needed to retrieve my cas.base.url. In my bean, I just had to do :

@Value("#{securityProperties['cas.base.url']}")
private String SSO_CAS_BASE_URL;

That's why I like Spring.

Friday, March 16, 2012

Google Groups Settings : an "how-to" solution without Google's Java API

I'm used to work with Google online services and my opinion is :
  • Google protocol is good (of course!) and I think that the direction which is taken to migrate to REST services is the good one.
  • the documentation is never up-to-date and often contains wrong code samples (which sometimes doesn't compile because it contains deprecated instruction calls or string values).
  • the Java API provides by Google is horrible. The support of Maven is still bad (it's better since of few months). It's confused between the provisioning API (GData library) and the Google Java Client API. Sometimes, you have to use the first one, sometimes the second.
  • the authentication methods are also confused. You have to choice between ClientLogin, AuthSub, OAuth1 and OAuth2 (and OpenID?) : what's the fuck? On OAuth, you have other choice to take because the authentication workflow is different if you application is on the web or embedded. This situation could be clearer and Google should refine its authentication politic. They should consider only authentication for administration apps (without code exchange and OAuth token cooking) and authentication for end-user apps.
So, I had some difficulties to work this the recent API for groups settings and I decided to share some piece of code. The idea of my code it NOT TO USE the Google Java Client API. I prefer to dialog directly with Google and to use the XStream lib to do that.

Here is my code to retrieve a group settings. It is not a code for an end-user apps (where you should use OAuth2 authentication). I use it for admin tasks :



public GoogleGroupConfiguration getConfiguration(String groupName) {

try {
String groupEmail = MY_GROUP_EMAIL;
URL url = new URL("https://www.googleapis.com/groups/v1/groups/" + groupEmail + "?key=MY_APP_KEY_OBTAINED_FROM_GOOGLE_CONSOLE_API&alt=json");
GoogleGroupConfiguration groupConfiguration = new GoogleGroupConfiguration();
HttpTransport transport = new NetHttpTransport();

// authenticate with ClientLogin
ClientLogin authenticator = new ClientLogin();
authenticator.username = MY_USERNAME;
authenticator.password = MY_PASSWORD;
authenticator.accountType = "HOSTED_OR_GOOGLE";
authenticator.authTokenType = "apps";
authenticator.transport = transport;
Response authenticate = authenticator.authenticate();
String authorizationHeaderValue = authenticate.getAuthorizationHeaderValue();

// make query request
HttpRequestFactory requestFactory = transport.createRequestFactory();
HttpRequest request = requestFactory.buildGetRequest(new GenericUrl(url.toString()));
request.getHeaders().setAuthorization(authorizationHeaderValue);
request.addParser(new JsonCParser(new JacksonFactory()));

// Make request and parse result
HttpResponse execute = request.execute();
String parseAsString = execute.parseAsString();
System.out.println(parseAsString);
JettisonMappedXmlDriver hierarchicalStreamDriver = new JettisonMappedXmlDriver();
XStream xstream = new XStream(hierarchicalStreamDriver);
parseAsString = "{\"" + GoogleGroupConfiguration.class.getName() + "\":" + parseAsString + "}";
xstream.fromXML(parseAsString, groupConfiguration);
return groupConfiguration;
} catch (Exception e) {
e.printStackTrace();
throw new GoogleAccessException(e);
}
}

public class GoogleGroupConfiguration {

public enum MessageDisplayFontEnum {
DEFAULT_FONT, FIXED_WIDTH_FONT
}

public enum MessageModerationLevelEnum {
MODERATE_ALL_MESSAGES, MODERATE_NEW_MEMBERS, MODERATE_NONE, MODERATE_NON_MEMBERS
}

public enum ReplyToEnum {
REPLY_TO_CUSTOM, REPLY_TO_IGNORE, REPLY_TO_LIST, REPLY_TO_MANAGERS, REPLY_TO_OWNER, REPLY_TO_SENDER
}

public enum WhoCanInviteEnum {
ALL_MANAGERS_CAN_INVITE, ALL_MEMBERS_CAN_INVITE
}

public enum WhoCanJoinEnum {
ALL_IN_DOMAIN_CAN_JOIN, ANYONE_CAN_JOIN, CAN_REQUEST_TO_JOIN, INVITED_CAN_JOIN
}

public enum WhoCanPostMessageEnum {
ALL_IN_DOMAIN_CAN_POST, ALL_MANAGERS_CAN_POST, ALL_MEMBERS_CAN_POST, ANYONE_CAN_POST, NONE_CAN_POST
}

public enum WhoCanViewGroupEnum {
ALL_IN_DOMAIN_CAN_VIEW, ALL_MANAGERS_CAN_VIEW, ALL_MEMBERS_CAN_VIEW, ANYONE_CAN_VIEW
}

public enum WhoCanViewMembershipEnum {
ALL_IN_DOMAIN_CAN_VIEW, ALL_MANAGERS_CAN_VIEW, ALL_MEMBERS_CAN_VIEW
}

private String kind;
private String email;
private String name;
private String description;
private WhoCanJoinEnum whoCanJoin;
private WhoCanViewMembershipEnum whoCanViewMembership;
private WhoCanViewGroupEnum whoCanViewGroup;
private WhoCanInviteEnum whoCanInvite;
private boolean allowExternalMembers;
private WhoCanPostMessageEnum whoCanPostMessage;
private boolean allowWebPosting;
private long maxMessageBytes;
private boolean isArchived;
private boolean archiveOnly;
private MessageModerationLevelEnum messageModerationLevel;
private ReplyToEnum replyTo;
private String customReplyTo;
private boolean sendMessageDenyNotification;
private String defaultMessageDenyNotificationText;
private boolean showInGroupDirectory;
private boolean allowGoogleCommunication;
private boolean membersCanPostAsTheGroup;
private MessageDisplayFontEnum messageDisplayFont;

public void setArchiveOnly(boolean isArchiveOnly) {
if (isArchiveOnly) {
this.whoCanPostMessage = WhoCanPostMessageEnum.NONE_CAN_POST;
}
if (this.archiveOnly && !isArchiveOnly) {
this.whoCanPostMessage = WhoCanPostMessageEnum.ALL_MANAGERS_CAN_POST;
}
this.archiveOnly = isArchiveOnly;
}

public void setWhoCanPostMessage(WhoCanPostMessageEnum newWhoCanPostMessage) {
if (newWhoCanPostMessage.equals(WhoCanPostMessageEnum.ALL_MANAGERS_CAN_POST)) {
this.messageModerationLevel = MessageModerationLevelEnum.MODERATE_NON_MEMBERS;
}
}

// ... add getters/setters

}



The idea is to get an auth token with the classic ClientLogin method. Then, I always put this token in each request header. Don't forget to add the API access key you can obtain from the Google console API. It allows you to access data you don't own (which is the case for administration batch processes). As you can see, I set alt=json into the request URL to get a json response. I created the GoogleGroupSettings class to map the Google response directly to an object through XStream.

If you already use AppsForYourDomain code, you can build requests without using the Clientlogin method. Create an AppsGroupService instance and work with GDataRequest.
I give you an example :



AppsGroupsService groupService = new AppsGroupsService(adminEmail, adminPassword, domain,"gdata-sample-AppsForYourDomain-AppsGroupService");
GDataRequest entryRequest = groupService.createEntryRequest(url);
entryRequest.execute();
InputStream inputStream = entryRequest.getResponseStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
for (int readBytes = inputStream.read(); readBytes >= 0; readBytes = inputStream.read())
outputStream.write(readBytes);
// Convert the contents of the output stream into a byte array
byte[] byteData = outputStream.toByteArray();
String parseAsString = new String(byteData);
parseAsString = "{\"" + GoogleGroupConfiguration.class.getName() + "\":" + parseAsString + "}";

// Parse result with XStream
JettisonMappedXmlDriver hierarchicalStreamDriver = new JettisonMappedXmlDriver();
XStream xstream = new XStream(hierarchicalStreamDriver);
xstream.fromXML(parseAsString, groupConfiguration);

// Close the streams
inputStream.close();
outputStream.close();


I hope this code will help you.


Thursday, February 09, 2012

Remember to put a timeout on your heartbeat pings

I'm working a distributed piece of software which needs to be disabled when a tier is not reachable. To do that, I developed a Spring bean (a java service class) and I scheduled a method on it (with a @scheduled annotation). This method makes some heartbeat pings on each tier. The java service class contains a flag which indicates if all is OK. If an heartbeat fails, this boolean status is set to false. Of course, thanks to Spring, I easily injected this class into my web pages. If a user tries to access to the application and the health status is set to false, he is automatically redirected to a page which indicates that the service is closed. But, let's go back to pings.

I scheduled my pings to be executed each minute. That was for me a good value. But, a problem appeared during my first real tests. I realized that pings durations could be longer than one minute because the network connect() method blocked my thread. Of course, I forgot to manage short timeouts!

After a few googlings, I found that : http://blog.smartkey.co.uk/2011/09/adding-a-thread-timeout-to-methods-in-java/

This is a quite simple code. I copied it here :

public void doWork() {
//perform some long running task here...
}

public void doWorkWithTimeout(int timeoutSecs) {

//set the executor thread working
final Future future = executor.submit(new Runnable() {
public void run() {
try {
doWork();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});

//check the outcome of the executor thread and limit the time allowed for it to complete
try {
future.get(timeoutSecs, TimeUnit.SECONDS);
} catch (Exception e) {
//ExecutionException: deliverer threw exception
//TimeoutException: didn't complete within downloadTimeoutSecs
//InterruptedException: the executor thread was interrupted

//interrupts the worker thread if necessary
future.cancel(true);

log.warn("encountered problem while doing some work", e);
}
}

Now, all is good for me and my heartbeat pings.

Tuesday, January 17, 2012

Use Spring 3 Expression Language (spEL) to get an Integer from an environment variable

Today, I played with Spring Batch. As you probably know, in a classic XML Spring config file, you can use ${my.property} to inject a system property in a bean attribute. That's quite simple.

But, in a JPA item reader (Spring Batch users should understand that), you cannot use this old syntax to inject values in your HQL query (using a parameterValues property). So, I decided to test the fabulously complicated spEL. A wonderful idea...

So, my problem is to get an Integer value from an argument passed to my JVM with something -Dmy.prop=value. Of course, if I don't have any JVM param, I want to have a default value.

Here is the solution :

#{(T(java.lang.Integer).parseInt(systemProperties['process.past.days']?:0))}

So, let's explain it :
  1. #{(systemProperties['process.past.days'])} is required to retrieve a system property called process.past.days
  2. #{(systemProperties['process.past.days']?:0)} is required if you want to set 0 as default value... but... it's horrible... system properties are Strings!!! So, let's parse it.
  3. #{(T(java.lang.Integer).parseInt(...))} is required to convert your String to an Integer
Waoooh! I did it!

My conclusion is that spEL is powerfull but too complicated. How could we maintain that in a few months or years?