Java and Cloud in 10 minutes? Jelastic!
4This weekend I wanted to experiment with a cloud solution for Java. In the past I tried out Google App Engine, but although easy and fast, it forces you to use the Google API and has some limitations.
This time, the criteria for the platform was running nearly anything in a web container. And I think I found the perfect match…
Introducing Jelastic
Jelastic is the next generation of Java hosting platforms which can run and scale ANY Java application with no code changes required.
- Easy to Create
- Easy to Deploy
- Easy to Scale
- Easy to Manage
Jelastic promises a lot: platform independence and run, scale any Java application with no code changes. That sounds too good to be true, but after reading this article, you too will be convinced this is no lie.
After registering on their website, you’ll immediately receive your login credentials and you can get started. At this moment they offer two datacenters worldwide: one in North America, and another for Europe. I choose Europe as my main hoster.
The most important part is next: creating and configuring a cloud environment for your project. As you can see on the picture, they offer both PaaS and IaaS . All necessary infrastructure is present in form of load balancers, SSL-termination and proper hardware. On top of that, you can determine the platform of your choice: many combinations are possible, you can choose between Tomcat, JBoss and Glassfish and one of many both SQL and NoSQL databases.
To finalize your environment you can tweak the horizontal and vertical scaling settings by increasing the cloudlets on each server (vertical) and the amount of servers (horizontal).
Since Jelastic is still in beta, the price tag for your extreme setup will be 0$ at the moment. I can live with that, so choose a name for your environment and create it!
Depending on your configuration, creating your environment can take from a few seconds to a few minutes.
Getting started
With your environment set up, you can start by deploying the sample web application to your environment, it’s a simple ‘Hello world’ application. When looking back, you just configured your own scalable cloud application that’s available on the web in only a few minutes…
Now you’re done, you can do virtually anything with your server and database. On the main dashboard, it’s as simple as uploading your war and deploying it.
Quick Sample
I created a simple web application that works around one entity, all using common frameworks and technologies. You can fork it at https://github.com/dvsander/Jelastic-RDTest.
I configured my environment with a MySQL database. Accessing it is extremely easy: the first time you visit the Database Webview, you receive a mail with phpMyAdmin credentials and the URL. After a few seconds I had root access to my MySQL instance and I created a database, a simple table and a user with enough rights to query it:
CREATE TABLE IF NOT EXISTS `Book` ( `id` int(11) NOT NULL auto_increment, `isbn` text NOT NULL, `title` text NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
My sample Maven2 project uses Hibernate as persistence provider, so all it takes it modifying the hibernate.cfg.xml :
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://<HOST>.jelastic.com/<DBNAME></property> <property name="connection.username"><USERNAME></property> <property name="connection.password"><PASSWORD></property> <property name="current_session_context_class">thread</property> <property name="show_sql">true</property> <mapping class="com.realdolmen.brains.demo.jelastic.model.Book" /> </session-factory> </hibernate-configuration>
Deploy the application to your environment and you got yourself a multi-layered web application in Java hosted in the cloud. Impressive isn’t it?
Conclusion
It’s very easy to get an application running on Jelastic.
Their motto of keeping everything easy, from development up to deployment, is no lie.
In code, there isn’t any reference to the platform and no specific limitations or API.
Jelastic is definitely something to watch out for. When they go live offering both free/low prices for starters and a decent SLA and competitive prices for business partners, I expect this to be a big player in Java cloud solutions.
At the moment I haven’t got bad experiences from using it. Should I in the future encounter some, I will edit this post.
Are you interested in cloud solutions? What services have you tried out?
Jira Remote API Calls – Making life easier
0JIRA is a well known Software-suite. In short, JIRA is a proprietary issue tracking product, maintained and developed by Atlassian. It is commonly used for bug tracking, issue tracking, and project management.
Background information
-
A service is analysed and then modelled into a BPMN diagram.
-
Functional Analysts use this diagram to create a Test Design for the given service and do general review.
-
Software Engineers take both the service design and the test design to write (super) code.
-
The service can be exposed publicly through web services. This means two extra tasks for the same service: creating of a public contract and integrating it with the application.
One service, or deliverable, can create up to 5 related tasks, each with their own work flow and transitions; totalling a whopping 6 JIRA issues in total. Every subTask is defined by a specific issueType and has individual custom fields associated with it.
You must be wondering, ‘why all this information? I came here to read about the JIRA Remote API and how I can use it!’. Well, with this information in hand, I hope you can imagine why I took the time to investigate in this matter. After all, I’m the one analysing and modelling the services, and thus inserting all these issues into the system…
Creating up to 6 JIRA issues with their own issueTypes, summary, custom fields for any given service takes a whole lot of time.
Therefore introducing,
The JIRA Remote API Calls
I was surprised how easy it was to get the Remote API up and running. Basically you just enable the ‘Accept remote API calls’ option in your General Configuration settings under the Administration tab. The moment you turn it on, the following URL should give you a nice response: http://your_jira_url/rpc/soap/jirasoapservice-v2?wsdl . This URL should put a smile on your face: JIRA gives you a nice SOAP WSDL response!
Here’s just a few of the many operations provided by the Remote API:
- createIssue(String, RemoteIssue)
- getIssueById(String, String)
- getProjectByKey(String, String)
- getUser(String, String)
- login(String, String)
- logout(String)
- getIssuesFromTextSearch(String, String)
- …
The basics – Authentication
<properties>
<axis.version>1.4</axis.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>axistools-maven-plugin</artifactId>
<version>1.3</version>
<dependencies>
<dependency>
<groupId>axis</groupId>
<artifactId>axis</artifactId>
<version>${axis.version}</version>
</dependency>
</dependencies>
<configuration>
<wsdlFiles>
<wsdlFile>jirasoapservice-v2.wsdl</wsdlFile>
</wsdlFiles>
<packageSpace>com.atlassian.jira.rpc.soap.client</packageSpace>
</configuration>
<executions>
<execution>
<id>wsdl2java-generation</id>
<phase>generate-sources</phase>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>axis</groupId>
<artifactId>axis</artifactId>
<version>${axis.version}</version>
</dependency>
</dependencies>
With the contracts and the necessary code generated, I started with authenticating myself to my local JIRA development machine. When the authentication is succesfull you receive a token-string. You’ll notice that most of the operations require this token as a parameter.
public static void main(String[] args) throws Exception {
final JiraSoapServiceServiceLocator soapLocator = new JiraSoapServiceServiceLocator();
final JiraSoapService soapService = soapLocator.getJirasoapserviceV2(new URL("http://192.168.0.221:8080/rpc/soap/jirasoapservice-v2"));
String authToken = soapService.login("admin", "admin");
System.out.println(String.format("Logged in with token %s",authToken));
soapService.logout(authToken);
}
Of course you need to change the URL and login credentials in the example above for your environment. The token is printed to the commandLine as proof that we are logged in.
To demonstrate the communication and the robustness of the API, I pass in wrong credentials and a nice Exception is thrown by the API:
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
faultSubcode:
faultString: com.atlassian.jira.rpc.exception.RemoteAuthenticationException: Invalid username or password.
faultActor:
faultNode:
faultDetail:
{}com.atlassian.jira.rpc.exception.RemoteAuthenticationException:null
{http://xml.apache.org/axis/}stackTrace:com.atlassian.jira.rpc.exception.RemoteAuthenticationException: Invalid username or password.
Advanced: creating issues
Now we’re logged in, we can experiment with all operations in the API. In this example I’ll be creating an issue with the least amount of effort required. The amount of code needed to create a standard issue is very minimal:
public static void main(String[] args) throws Exception {
final JiraSoapServiceServiceLocator soapLocator = new JiraSoapServiceServiceLocator();
final JiraSoapService soapService = soapLocator.getJirasoapserviceV2(new URL("http://192.168.0.221:8080/rpc/soap/jirasoapservice-v2"));
final String authToken = soapService.login("admin", "admin");
System.out.println(String.format("Logged in with token: %S", authToken));
try {
final RemoteIssue issueToCreate = new RemoteIssue();
issueToCreate.setProject(myProjectKey); // use the key of your project
issueToCreate.setSummary("This will be the summary or 'title' of my issue");
issueToCreate.setType("3"); // Task
final RemoteIssue createdIssue = soapService.createIssue(authToken, issueToCreate);
System.out.println(String.format("Created issue with id %s", createdIssue.getId()));
} finally {
soapService.logout(authToken);
}
}
Notice the hardcoded values in the issueToCreate. This is because I removed some code for showcase purposes. In real situations, I suggest you use API operations like getProjectByKey, getIssueTypesForProject to use serverside values and thus making your code more dynamic. The same goes for custom fields, fixVersions and other values.
Advanced: creating Sub Tasks
Now a tricky part. I told you my client (and by this, me) is using JIRA 4.3.4. Well, creating SubTasks using the SOAP API is only supported as of Jira 4.4 ! In the 4.4 API there is a nice operation added in the WSDL : createIssueWithParent(String, RemoteIssue, String). This operation is absent in JIRA 4.3.4.
Since we can’t force our client to upgrade their JIRA, this was a bit of a disappointment. I was getting acquainted with the API, creating my parent issues , and now this…
I knew other projects worked around this issue.. I opened the sources of the Jira CLI project and found confirmation for my theory: creating subtasks wasn’t possible using the Remote API over SOAP.
This is why I love Java and Open-Source
The workaround is a form submit to the web page, just like a user would do in the web interface. This solution comes with a risk, since you basically do a http request/response cycle with no validation whatsoever. Should you, like me, opt for this approach, please do proper validation: http response OK, no errors on screen, form submitted ok, …
Here is an example of the most basic code to create a subtask using a form submit. Please add the following dependency to your project to make it compile:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.1.2</version> </dependency>
Some important notes:
- The username/password must be passed
- The X-Atlassian-Token header makes JIRA skip form validation, without this it doesn’t work
- Should you be interested in this approach, please use JIRA CLI (or its sources) to do proper validation of the response
This is the essential code, without validation, to create a subtask in the Remote API for JIRA 4.3.4:
public class Example {
public static void main(String[] args) throws Exception {
final JiraSoapServiceServiceLocator soapLocator = new JiraSoapServiceServiceLocator();
final JiraSoapService soapService = soapLocator.getJirasoapserviceV2(new URL(
"http://192.168.0.221:8080/rpc/soap/jirasoapservice-v2"));
final String authToken = soapService.login("admin", "admin");
System.out.println(String.format("Logged in with token: %S", authToken));
try {
final RemoteProject project = soapService.getProjectByKey(authToken, "KBOBCE");
final RemoteIssue issueToCreate = new RemoteIssue();
issueToCreate.setProject(project.getKey());
issueToCreate.setSummary("Parent - This will be the summary or 'title' of my issue");
issueToCreate.setType("3"); // Task
final RemoteIssue createdIssue = soapService.createIssue(authToken, issueToCreate);
System.out.println(String.format("Created issue with id %s", createdIssue.getId()));
RemoteIssue subTask = new RemoteIssue();
subTask.setSummary("SubTask - This will be the summary or 'title' of my issue");
subTask.setType("5"); // Sub-Task
createSubTaskUsingHttpPost(createdIssue.getId(),project.getId(), subTask);
} finally {
soapService.logout(authToken);
}
}
private static void createSubTaskUsingHttpPost(String parentIssueId, String projectId, RemoteIssue issue) throws Exception {
HttpClient httpClient = new DefaultHttpClient();
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("os_username", "admin"));
params.add(new BasicNameValuePair("os_password", "admin"));
params.add(new BasicNameValuePair("parentIssueId", parentIssueId));
params.add(new BasicNameValuePair("pid", projectId));
params.add(new BasicNameValuePair("issuetype", issue.getType()));
params.add(new BasicNameValuePair("priority", "3")); //Major
params.add(new BasicNameValuePair("assignee", "-1")); // Automatic
params.add(new BasicNameValuePair("description", issue.getDescription()));
params.add(new BasicNameValuePair("environment", issue.getEnvironment()));
params.add(new BasicNameValuePair("priority", issue.getPriority()));
params.add(new BasicNameValuePair("reporter", "admin"));
params.add(new BasicNameValuePair("summary", issue.getSummary()));
URI uri = new URI("http://192.168.0.221:8080/secure/CreateSubTaskIssueDetails.jspa");
uri = URIUtils.createURI(uri.getScheme(), uri.getHost(), uri.getPort(), uri.getPath(), URLEncodedUtils.format(params, "UTF-8"),
null);
final HttpGet httpget = new HttpGet(uri);
httpget.addHeader("X-Atlassian-Token", "no-check");
httpget.addHeader("Content-Type", "application/xml");
httpget.addHeader("Accept", "application/xml");
final ResponseHandler<String> handler = new ResponseHandler<String>() {
public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
System.out.println(String.format("StatusLine %S", response.getStatusLine()));
HttpEntity entity = response.getEntity();
if (entity != null) {
return EntityUtils.toString(entity);
} else {
return null;
}
}
};
final String htmlRresponse = httpClient.execute(httpget, handler); // TODO: Pretty please check the response for errors
System.out.println(String.format("HtmlResponse: %s", htmlRresponse));
}
}
In conclusion
My experience with the JIRA Remote API has been quite positive. As this article points out, it’s very easy to get started. Remotely interacting with your JIRA instance has never been easier. The Remote API is under continuous development.
On the downside, I was disappointed to find out that basic functionality like creating subTasks wasn’t supported in my Jira Version (4.3.4). Though a fix was provided, most of the time you can’t just patch a JIRA instance used by a whole organization.
I’m happy to see that Atlassian is streamlining their Remote API. Their focus in the future will be the REST-interface.
References used
Jira 4.3.4 JiraSoapService API -Online JavaDoc for the JiraSoapService
Jira Command Line Interface – A plugin, subproject actually, providing access to your JIRA instance using the commandline. It’s very complete and is well maintained.
Jira RPC Service overview – An overview of the current and future developments of Atlassian in their Remote API/RPC
Pecha Kucha – Gamification
2Vrijdag 16 december was het laatste Java Café van 2011. Ondanks het gure weer en de (aangekondigde) BOB-campagne hebben een 30-tal collega’s de avond gezellig en droog doorgebracht in Introvert, Gent. Naast een lekkere maaltijd stonden een technology speed dating en een Pecha Kucha,gepresenteerd door ondergetekende, op het menu.
Ik schrijf deze blog niet enkel om de Powerpoint te delen, maar ook om eens te vertellen over hoe ik begonnen ben aan deze nieuwe frisse aanpak van presentaties.
Voor de ongeduldigen, hier is de presentiatie:
Wat is een pecha kucha
Om geen open deur in te trappen zijn hier enkele URL’s waar je je kunt inlezen: Wikipedia, pecha-kucha.org, Vacature.com.
Pecha Kucha is een originele manier om ideeën over te brengen aan een publiek. Het volgt de 20×20 regel: 20 slides, 20 seconden elk, wat een totaal van 6 minuten 40 seconden geeft aan de spreker. Dit kader dwingt de spreker om geen overbodige informatie op slides te zetten en enkel de kern van zijn boodschap over te brengen op een visuele manier. Wanneer je zoekt op youtube kun je enkele goede voorbeelden vinden van Pecha Kucha presentaties.
Waarover kun je het hebben
Maakt echt niet uit. Alles is mogelijk, zolang je het zelf maar interessant kunt overbrengen op je publiek. Er is helemaal geen verplichting om het over werk te hebben.
Hoe ben ik er aan begonnen
Alles begint met een idee. Ik lees in mijn vrije tijd blogs en artikels op het internet en vond gamification wel de moeite waard om eens 6 minuten over te vertellen.
Ik ben beginnen zoeken op Slideshare naar presentaties over dit onderwerp door andere sprekers. Ik heb mij gebaseerd op twee presentaties, van samen +300 slides. Dit werd ingekort naar een verhaal met volgende voorbereiding:
- Welk gedrag of welke toepassingen kan ik aanspreken in het publiek zodat ze onmiddelijk weten waarover het gaat (hoe impacteert mijn idee hen)
- Welke voorbeelden uit dagelijkse activiteiten kan ik toelichten
- Wat is gamification
- Waar gebruikt men gamification (met bekende voorbeelden)
- Waar moet je op letten bij gamification, wat zijn de pitfalls
Dit verhaal goot ik dan samen met behulp van afbeeldingen en visuele elementen die ik op internet vond.
Presentatie zelf
Over inhoud kon ik nog enkele minuten blijven voorpraten
Toch enkele pointers:
- Beperk je pecha kucha tot 1 enkel idee, en wijk hier niet van af. Beter 1 consistent verhaal dan onsamenhangende oneliners
- Aan oneliners en krachtige zinnen heb je voldoende. Een voorbereiding met volzinnen is helemaat niet nodig.
- Oefen thuis het 20×20 kader, 20 seconden is helemaal niet veel.
Conclusie
De ervaring van zelf een Pecha Kucha te geven is zeker aan aanrader. Het maakt je veel bewuster van wat een presentatie goed maakt. De focus die je als spreker moet leggen op je verhaal, rekening houdend met het kader ( 20×20 ), doen je stil staan bij de kern van een presentatie: een boodschap overbrengen op je doelpubliek.
Unix Background Jobs 101
0On my current project I’m working with a virtual Ubuntu machine on which Weblogic and DB2 are installed. Weblogic starts with the ./startWeblogic.sh command, and log files are written to a logfile ‘weblogic.xml’ :
./startWebLogic.sh > weblogic.log
You may go wild with opening multiple terminals and switching between them, but I hate the fact that the weblogic process is just taking up an entire window, even though it’s essentially meant to be a background process! This is where some basic unix commands kick in: run a long-lasting command or script as a background job, execute it in the background, bring it back to the foreground, see all running background jobs and (possibly) kill them. Let’s go.
Spawning a background job
This code fragment simulates a 10second command. Notice that the cursor isn’t available until the 10seconds are over.
sleep 10
Append your command with an ampersand ( & ), to run it in the background. The cursor is immediately available.
sleep 10 &
You may wonder already, ‘but how do I know the command is finished?’. See the chapter about ‘showing all background jobs’ for that.
Send the current executing command to the background and back
Suppose you forgot the & , or a command is taking longer than expected. You don’t need to quit (CTRL-C) the command, and re-execute it with the &. You can send the current executing command to the background by pressing CTRL-Z.
sander@sander-ThinkPad-T510:~$ sleep 20 ^Z [1]+ Stopped sleep 20
Notice the fact that the job was stopped (paused should be a better name). Execute the bg command to make the job continue.
sander@sander-ThinkPad-T510:~$ bg [1]+ sleep 20 & sander@sander-ThinkPad-T510:~$ fg sleep 20
To demonstrate this, you can execute thefg command to make it come back to the foreground again. You can bring back any background job to the foreground using this command. No parameters will show the most recent background job, passing %1 will show process with id 1, %2 with id 2, etc.
You can bring a background job to the foreground using fg command. When executed without arguments, it will take the most recent background job to the foreground.
Showing all background jobs
When using this technique a lot, you might send multiple commands to the background. To show all current background process, execute the jobs command.
sander@sander-ThinkPad-T510:~$ jobs [1] Running sleep 30 & [2]- Running sleep 25 & [3]+ Running sleep 20 &
Killing background jobs (OPTIONAL)
Suppose you sent a command to the background you want to kill immediatly. The kill commando can’t only kill processes, but also background jobs.
sander@sander-ThinkPad-T510:~$ sleep 25 & [1] 21153 sander@sander-ThinkPad-T510:~$ sleep 25 & [2] 21156 sander@sander-ThinkPad-T510:~$ sleep 25 & [3] 21157 sander@sander-ThinkPad-T510:~$ kill %2 sander@sander-ThinkPad-T510:~$ jobs [1] Running sleep 25 & [2]- Terminated sleep 25 [3]+ Running sleep 25 &
VisualVM 1.3.2 released. Profiling and monitoring on the JVM
2VisualVM is a tool to monitor and troubleshoot Java applications. It runs on Oracle/Sun JDK 6, but is able to monitor applications running on JDK 1.4 and higher. It utilizes various available technologies like jvmstat, JMX, the Serviceability Agent (SA), and the Attach API to get the data and automatically uses the fastest and most lightweight technology to impose minimal overhead on monitored applications.
With the out-of-the-box features it perfectly fits all the requirements of application developers, system administrators, quality engineers and – last but not least – application users submitting bug reports containing all the necessary information.
This is definitely a tool to check out!
See the video for yourself, it shows all the features! Or take it for a spin!
Features
| Feature | JDK 1.4.2 local/remote |
JDK 5 local/remote |
JDK 6 local |
JDK 6 remote |
| Overview | ![]() |
![]() |
![]() |
![]() |
| System Properties (in Overview) | ![]() |
|||
| Monitor | ![]() |
![]() |
![]() |
![]() |
| Threads | ![]() |
![]() |
![]() |
|
| Profiler | ![]() |
|||
| Thread Dump | ![]() |
|||
| Heap Dump | ![]() |
|||
| Enable Heap Dump on OOME | ![]() |
|||
| MBean Browser (plugin) | ![]() |
![]() |
![]() |
|
| Wrapper for JConsole plugins (plugin) | ![]() |
![]() |
![]() |
Google App Engine with JSF2, CDI
5Last night I wanted to play around with the Google App Engine. Google’s cloud service should ring a bell? Don’t worry if it doesn’t, you can read more about it and use this tutorial as your first GAE-project!
Due to my interest in JEE6-technologies, I was interested whether the latest Google App Engine (1.4.3) supported the latest technologies in Java: JSF2 for the view layer, and CDI ( Contexts and Dependency Injection for the Java EE Platform ) to wire everything up.
In this article I will briefly discuss what problems I have encountered while setting up this environment.
Shortcut: If you’re only interested in the result, and want to get started right away, you can download the full eclipse project here. No GAE or CDI dependencies!
Project Setup
JSF2 on the Google App Engine
To get started, I advise you to follow the guide ‘Configuring JavaServer Faces 2.0 to run on the Google App Engine Using Eclipse‘ described on the Google website. It is pretty much complete, well documented with screenshots, and a breeze to follow.
The guide will set up your IDE, configure the Google App Engine plugin, download and configure the required libraries for setting up JSF2 on the Google App Engine.
Adding CDI
Download Weld 1.1.1-FINAL. Extract the download, it contains the following libraries which you need to add to the build path:
- cdi-api.jar
- weld-api.jar
- weld-core.jar
- weld-servlet.jar
Add the following listener to your web.xml :
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
To finalize the configuration of CDI in your GAE-application, add an empty beans.xml file to your WEB-INF folder. This is needed by default by CDI to enable classpath scanning.
Problems encountered
Startup fails – InitialContext
After following the Google tutorial on setting up JSF2 on GAE, you’ll notice something odd. Yes, your application isn’t starting up!
This is the stracktrace:
WARNING: Error starting handlers java.lang.NoClassDefFoundError: javax.naming.InitialContext is a restricted class. Please see the Google App Engine developer's guide for more details. at com.google.appengine.tools.development.agent.runtime.Runtime.reject(Runtime.java:51) at com.sun.faces.config.WebConfiguration.processJndiEntries(WebConfiguration.java:578)
As you can see, the com.sun.faces.config.WebConfiguration class tries to load up an InitialContext in the processJndiEntries method. The InitialContext class is not allowed by the Google App Engine for obvious reasons.
When we take a look into the WebConfiguration.java class ( love open-source! ), we can clearly see the InitialContext being loaded:
private boolean canProcessJndiEntries() {
try {
Util.getCurrentLoader(this).loadClass("javax.naming.InitialContext");
} catch (Exception e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(
"javax.naming is unavailable. JNDI entries related to Mojarra configuration will not be processed.");
}
return false;
}
return true;
}
The App Engine is freaking out and throws the restricted class exception. Thanks to open-source we can clearly see what’s going on, and modify it to our own needs. Since we don’t need any JNDI-lookups, we can safely remove this method.
Copy paste the original java sourcefile to the same package in your project (com/sun/faces/config/), and comment out all references to the InitialContext.
You can download the result, for version jsf-impl-2.0.2-FCS.jar, here.
Enable Sessions
Sessions are disabled by GAE by default. The following exception is thrown.
java.lang.RuntimeException: Session support is not enabled in appengine-web.xml. To enable sessions, puttrue in that file. Without it, getSession() is allowed, but manipulation of sessionattributes is not. at com.google.apphosting.utils.jetty.StubSessionManager$StubSession.throwException(StubSessionManager.java:77) at com.google.apphosting.utils.jetty.StubSessionManager$StubSession.setAttribute(StubSessionManager.java:65)
The exception is well documented; as mentioned, you need to put
JSF configuration
- GAE supports server state saving, so use the javax.faces.STATE_SAVING_METHOD param
- Projectstage can be any one of the phases
- The expressionfactory needs to be explicitly set due to a GAE-bug
- We enable the xml validation checks
- Spawning threads is disallowed in GAE. By setting the com.sun.faces.enableThreading param to false, JSF will not spawn childthreads
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.validateXml</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.enableThreading</param-name>
<param-value>false</param-value>
</context-param>
References
- Google Guide to configuring JSF 2.0 to run on the Google App Engine. I used this guide myself to get started, but some errors I encountered aren’t discussed in it. (link)
- Article discussing the solution to the ‘javax.naming.InitialContext is a restricted class’ problem. (link)
- JavaServer Faces 2.0 and Google App Engine Compatibility Issues (link)
Opportuniteiten bij onderhoudsprojecten
0Mijn vorige projecten waren allemaal Greenfield projecten, projecten die van scratch begonnen en waar ik een grote vrijheid kreeg om te ontwikkelen. Die vrijheid kon ik als ontwikkelaar benutten om nieuwe technologieën te introduceren, het component design zo ‘mooi’ mogelijk te maken, laatste versies van libraries gebruiken, en zo meer. Je gebruikt ook je ervaring om alles zo perfect mogelijk te maken en je te houden aan coding conventions, best practices, guidelines op te stellen. Dit zijn de soort projecten waar iedereen zich wel kan in vinden, niet?
Het klantenverhaal…

In September vorig jaar kreeg ik het nieuws dat ik kon beginnen bij een grote klant. Het is een mastodont van een overheidsinstelling: veel postjes in te vullen, veel projecten, veel bedrijven die ‘binnen proberen geraken’. Kortom, er zijn veel consultants die lange tijd op verschillende projecten meedraaien.
De applicatie draait op Struts 1.3.9, EJB3′s, een zelfgebouwd persistency-framework, een ononderhouden codebase met duplicatie van code, hacks, ‘everything-on-the-session’, String concatenation van soms +40 lijnen(dat is een widescreen laptopscherm vol met lijnen!), 614 VO’s BO’s BC’s Actions Forms zonder hergebruik, constants her en der, geen documentatie, you name it. De schok was groot.
Challenge Accepted!
Ik geef toe, ik had m’n twijfels toen ik dit project aanvaardde. Mijn grootste twijfel was of ik hier wel iets uit ging leren? Struts1, onderhoud, jsp’s, *geeuw*. Achteraf bekeken heb ik andere dingen bijgeleerd op dit project. Ik besefte dit pas toen ik het artikel ‘The Joys of Maintenance Programming‘ las enkele weken terug.
Je leert debuggen
Iedereen weet ondertussen wel hoe hij debugged. Breakpoints zetten, je kent je component diagram, soms weet je gewoon al waar je moet kijken zonder te debuggen! Ik heb ondervonden dat het veel meer inspanning en doorzettingsvermogen vraagt om andermans code te begrijpen en te lezen. Stap voor stap moet je de oorzaak van het probleem proberen achterhalen. Misschien gebeurt er op andere plaatsen nóg meer? Of wordt het misschien herbruikt? Je kunt dus niet zomaar veronderstellingen maken, maar je moet je volledig ‘inleven’ in de code.
Het lezen en debuggen van vreemde code doet je nadenken over hoe de code (niet) werkt, in plaats van wat je denkt dat het zou moeten doen.
Je leert beter programmeren
Het is duidelijk uit voorgaand punt dat het gemakkelijker is om goede code te debuggen dan slechte code. Goede code kan (hopelijk
) iedereen hier schrijven. Maar wat is slechte code? Wel, dit onderscheid zal je zeker en vast ondervinden op een onderhoudsproject. Je zult de ‘waarom’ achter code moeten achterhalen, wat de bedoeling was van de programmeur. Ervaren programmeurs herkennen onmiddelijk het verschil tussen goede en slechte code, en omgaan met ‘meer code’ (niet enkel die van jou of andere ervaren mensen) zal dit gevoel enkel versterken.
Je ontwikkelt manieren om je weg te vinden in een onbekende codebase, en je zult een neus ontwikkelen voor code waar een reukje aan zit.
Je leert optimaliseren
De originele programmeurs hebben hun premature optimizations al kunnen doen (niet door laten verleiden! Premature optimization is the root of all evil). Jij kunt nu de échte efficiëntieproblemen en bottlenecks vaststellen. De originele programmeurs staken veel tijd en energie in wat zij als mogelijk performantieprobleem zagen. Problemen die misschien nooit zouden voorgevallen zijn, of die geen grote impact zouden gehad hebben.
Werkende systemen hebben reële performantieproblemen. Het is een heel nobele vaardigheid die de gebruikers zeker positief zullen onthalen om deze problemen te identificeren en er oplossingen voor te formuleren. Het zoeken en oplossen van deze problemen kan zelf leuk worden!
Klanten merken altijd wanneer je hun applicatie sneller maakt, en appreciëren het enorm wanneer je er aan denkt om ze efficiënter te maken.
Je leert met gebruikers omgaan
Bij greenfield projecten werk je vooral binnen het team. De analye is klaar, de business is gecontacteerd, de requirements liggen vast (althans, dat hoop je altijd). Nieuwe applicaties hebben geen echte gebruikers, je krijgt use cases en stakeholders. Bij onderhoudsopdrachten werk je met de eindgebruikers, vooral diegene die de applicatie dagelijks gebruiken en die zich ergeren aan de bugs of aan functionaliteit die niet of slecht werkt.
Communiceren met eindgebruikers die uit een niet-IT-achtergrond komen doet je uit je IT-schelp kruipen. Hierdoor voel je je meer betrokken tot je werk.
This post was mentioned on RealDolmen NoNonsense Blog, and DZone
SFTP Server communication in Java using Jsch
9Last week I had to write a Java software component that could connect to a SFTP server, read in flat files, process them through a business component, and then place a generated file back on the same server.
The technical details about the SFTP protocol were unclear to me, so I started reading about it on wikipedia. Basically SFTP is the same as SCP, a secure copy over SSH.
Setup of a development environment
Before anything else, I needed a SFTP server installed for development. I choose the trial version of the complete FTP suite-trial version. This isn’t the only, nor the best SFTP server-suite out there. I can imagine using proftpd, ssh, core ftp, or other ftp software.
The only next big thing I had to do was generate a public/private keypair to authenticate myself, PuTTy gen came to the rescue. In my Server admin screen I linked the key to the user account and I was ready to start developing.
JSch
The search for existing Java libraries that helped me working with this SFTP server, didn’t yield the results I was hoping for. There wasn’t a ‘best’ or ‘winning’ API or framework that emerged from the search results.
I found that Jsch was not only used by some big reference applications ( Ant(1.6 or later), Eclipse(3.0), NetBeans 5.0(and later), Maven Wagon, JIRA, and more), but it was also available in the Maven2 repository as a standalone library. I checked out the examples on their website, and found them to be very clear to me. These are also available on my Maven2 demo-project which you can find below.
All in all, I developed a small ‘push’ and ‘get’ component in my project in notime. You can find the relevant code attached to this post. You might think that this API is very lowlevel: commands as “ls”, “mkdir”, “get”, “cd”, … are all avaible in simple method calls. In my opinion, this is a good thing, because in these matters you want to have full control over your communication with the server.
Demo
This Demo will try connect to a given sftp server, list all directories and files in the home directory and exit. For getPrivateKeyAsByteStream(); implementations, take a look at FileUtils in apache-commons or look for code online.
To run this demo, you should either include Jsch on your classpath, or download my Maven2 project here.
public class SftpDemo {
private static final String HOST = "127.0.0.1";
private static final int PORT = 22;
private static final String USER = "test";
private static final String PRIVATE_KEY_LOCATION = "C:\\sftpkeys\\private_openssh";
public static void main(String[] args) throws Exception {
JSch.setLogger(new MyJschLogger());
JSch jSch = new JSch();
final byte[] privateKey = getPrivateKeyAsByteStream();
final byte[] password = "certPass".getBytes();
jSch.addIdentity(USER,
privateKey,
null,
password
);
// TODO: remove this line in real life. Work with known_hosts!
Session session = jSch.getSession(USER, HOST, PORT);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
Channel channel = session.openChannel("sftp");
ChannelSftp sftp = (ChannelSftp) channel;
sftp.connect();
final Vector files = sftp.ls(".");
Iterator itFiles = files.iterator();
while (itFiles.hasNext()) {
System.out.println("Index: " + itFiles.next());
}
final ByteArrayInputStream in = new ByteArrayInputStream(
"This is a sample text".getBytes());
sftp.put(in, "test.txt", ChannelSftp.OVERWRITE);
sftp.disconnect();
session.disconnect();
}
This logger is a standard implementation, taken from the JSch-examples. It’s nice to see what’s happening behind the scenes. You should opt for logging frameworks when using Jsch in your project (and in all other cases too of course).
static class MyJschLogger implements Logger {
static java.util.Hashtable name = new java.util.Hashtable();
static {
name.put(new Integer(DEBUG), "DEBUG: ");
name.put(new Integer(INFO), "INFO: ");
name.put(new Integer(WARN), "WARN: ");
name.put(new Integer(ERROR), "ERROR: ");
name.put(new Integer(FATAL), "FATAL: ");
}
public boolean isEnabled(int level) {
return true;
}
public void log(int level, String message) {
System.err.print(name.get(new Integer(level)));
System.err.println(message);
}
}
}
Holiday’s over, what’s next ?
0At last, back in Belgium behind my desk and finding some time to write something.
New York is amazing, it opens up your view over the world. Words cannot describe the feeling when sitting on the red stairs in Times Square, feeling the everlasting energy and vibes of Times Square.
After 7 days of exploring the citylife, the two weeks at the Belgian Coast were very welcome.
In a few days I will be recommencing my daily job as a Java Software Engineer and blogging things as they happen.




