quinta-feira, 19 de dezembro de 2013
Using JAX-RS 2.0 to build an app from scratch.
Hi every one,
I would like to share with my friends my last article about JAX-RS 2.0. This article has been published this month (December) in the Brazilian Java Magazine and it shows, with a practical example, how to develop a full app using the new stuff of this spec.
Unfortunately, this time I could not share its content, but for those who live in Brazil I would recommend to buy one magazine in the nearest newsstand. :-). For those who live outside of Brazil I can only share the source code with you :-(
source code: https://github.com/fbrubbo/BrazilianJavaMagazine
Anyway.. Thanks for reading.
domingo, 11 de agosto de 2013
Running Websockets on OpenShift
WebSocket is a pretty new and important technology in which it is possible to send message frames from server to clients without opening multiple HTTP connections. Although it is has been proven to be a solid and consolidated specification, running websockets in the existing cloud platforms is still a pain in the ass. The main cloud players do not provide enough support for WebSocket protocol due to the lack of application servers’ readiness and due to other issues related to the routing layer.
Knowing those difficulties, I’ve decide to post the steps to help eager people to use Red Hat OpenShift PaaS to run a websocket apps in the cloud. So, let's start from the beginning.
- Then you must add a new application
- Pick Do-It-Yourself (DIY) cartridge
- This will allow you to use a “pure Linux server” to do whatever you would like to do. In the specific case of this post, we are going to install an embedded web application in order to provide the required support for websockets.
- Once DIY cartridge have been selected, you must fill out the application name and click on ‘Create Application’ button
- Finally, do a ‘git clone’ according instructions
At this point, we have already prepared our Linux server on the cloud to install our application according our needs. Now, let’s make the required changes in the working copy we have just cloned from OpenShift master repository.
The changes are:
The changes are:
- Update the shell script file which will be used by OpenShift to start our app
- File: .openshift/action_hoooks/start
- Content:
#!/bin/bash
# The logic to start up your application should be put in this
# script. The application will work only if it binds to
# $OPENSHIFT_DIY_IP:8080
echo "Starting WebSocketExample............. $OPENSHIFT_DIY_IP:$OPENSHIFT_DIY_PORT"
nohup java -jar $OPENSHIFT_REPO_DIR/diy/WebSocketExample.war > $OPENSHIFT_DIY_DIR/logs/server.log 2>&1 &
echo "Started WebSocketExample............. $OPENSHIFT_DIY_IP:$OPENSHIFT_DIY_PORT"
|
- Update the shell script file which will be used by OpenShift to stop your app
- File: .openshift/action_hoooks/stop
- Content:
#!/bin/bash
source $OPENSHIFT_CARTRIDGE_SDK_BASH
echo "Stopping WebSocketExample............."
if [ -z "$(ps -ef | grep WebSocketExample.war | grep -v grep)" ]
then
client_result "WebSocketExample Application is already stopped"
else
echo "Killing WebSocketExample............."
kill `ps -ef | grep WebSocketExample.war | grep -v grep | awk '{ print $2 }'` > /dev/null 2>&1
fi
echo "Stopped WebSocketExample............."
|
- Add the embedded jetty application in the ‘Do It Yourself’ directory
- Directory: diy
- In this example, we have used the ‘WebSocketExample.war’ app name in order to match out our start/stop scripts.
- Important note about the embedded jetty application file:
- There are some peculiaridades in the implementation of the class com.embedded.JettyStarter (shown below in red) which must be changed in order to bind the embedded app to the right IP and PORT number in the OpenShift platform.
- Content:
public class JettyStarter {
public static void main(String[] args) throws Exception{
ProtectionDomain domain = JettyStarter.class.getProtectionDomain();
URL location = domain.getCodeSource().getLocation();
// create a web app and configure it to the root context of the server
WebAppContext webapp = new WebAppContext();
webapp.setDescriptor("WEB-INF/web.xml");
webapp.setConfigurations(new Configuration[]{ new AnnotationConfiguration()
, new WebXmlConfiguration(), new WebInfConfiguration(), new MetaInfConfiguration()
//, new FragmentConfiguration(), new EnvConfiguration(), new PlusConfiguration()
});
webapp.setContextPath("/");
webapp.setWar(location.toExternalForm());
// starts the embedded server and bind it to openshift variables
String host = System.getenv("OPENSHIFT_DIY_IP");
String port = System.getenv("OPENSHIFT_DIY_PORT");
System.out.println(host + ":" + port);
InetSocketAddress sa = new InetSocketAddress(getByName(host), valueOf(port));
Server server = new Server(sa);
server.setHandler(webapp);
server.start();
server.join();
}
}
|
After script files have been configured and the embedded application has been put in the ‘diy’ directory, you must commit and push changes back to the master repository.
- The commands are:
- git commit -m 'My changes'
- git push
- As soon as the push finishes, the stop/start scripts will run
- If you notice it didn’t run accordingly, remote access your openshift server and check if everything is ok. Remember: it is Red Hat Linux, so you should be ok checking your stuff.
- Try to check if start/stop scripts have execution permission (not sure why, but I have this issue in some experiments).
- ls -lt $OPENSHIFT_REPO_DIR/.openshift/action_hooks/
Finally, are done. \o/
Access 'ws://[YOUR APP].rhcloud.com:8000/example' using your favorite WebSocket tool and check it by yourself.
- Important: due to issues related to the routing layer, OpenShift platform allow websockets only in the port number 8000.
Don't have a WebSocket tool? Take a look on ‘Advanced REST client’ for Chrome
domingo, 21 de julho de 2013
Points are all about sizing. So, avoid the word estimation!
How should we punctuate a certain task/story?
It is a recurrent discussion in our company and clients. From time to time I found myself arguing about this subject. This made me write down an example I’m used to put in those discussions.
Suppose you work in a team which is responsible for making article summaries for a newspaper. Then, someone in the team heard about a technique which uses points for sizing the amount of work. The team, though, decided to implement this technique and, after some discussions, everybody agreed to make sizing meetings (the event in which each person on the team give points to articles) as simple as possible. For that, they have chosen that each English full written article page would receive 1 (one) point.
In my opinion, it was a very good start for this team. Don't you think?
Then, the first article arrived. It had 10 written pages and then the team gave it 10 points. Then, the second article came with 20 pages, but 6 of them have lots of images. So, the team discussed a little bit and they agreed to give it 17 points.
Up until now, pretty simple. No?!?
But, some Portuguese articles became to arrive. The first one was a paper with 15 full written pages. How many points do you think the team would give to this article?
Think a few moments about it. I’ll be waiting right here. ;-)
Probably you would be thinking: “as a member of this team, I would give it more than 15 points because I’m not fluent in Portuguese and, therefore, it will take me more time to finish my work”.
If you have these thoughts I would say you are not sizing. You are, actually, trying to estimate.
But... What is the difference?
- Sizing
- The amount of work of a specific task
- Estimation
- Although sizing is a kind of estimation, the word estimation usually remember the amount of time, money and resources you will spend to perform a specific task
So... If more than 15 points are not appropriated, what would be a good number?
15, of course.
But why?
When you are sizing you must not consider complexity, time, money, resources and etc. Moreover, you should not take into account that you must learn something in order to perform a defined task (which is the case in this fake example).
But, again... Why?
- Time and complexity are very subjective measures
- For example, suppose you have a member of your team which is fluent in Portuguese and another which has never read a word in such a language. If they take into account time and/or complexity, they will think differently while punctuating. In other words, they may never reach a consensus about the amount of work.
- The amount of time, complexity and money depends on who will be performing the task
- In the most of cases, during the sizing meeting, we do not know exactly who will be responsible to perform a defined task. So, we must think in a generic way. For that, the most effective strategy is to relative tasks/stories to each other (i.e. sizing).
- Points help focus on team performance, not on individuals
- The idea behind points is to help give focus on the overall team result/capacity, and not on a specific team member performance.
- The team velocity is not possible to be measured correctly if time/complexity/etc are considered
- Suppose a year ago your team has given 20 points to a 10 pages article written in Portuguese. Considering this team got some fluency in that language, nowadays an article with the same number of pages is used to receive 15 points. At first glance it seems ok to give fewer points to it because the work is finished faster. However, if you do that, the velocity (commonly used in agile methodologies) will decrease (i.e. if a year ago you were able to deliver 200 points per month, now you can make only 150 - 180). If the learning curve was not taking into account the team velocity would be increased showing they are able to do more stuff in the same amount of time.
Making it short:
Points are all about sizing. If a year ago you gave to a specific task 10 points; right now, whenever you have to repeat that task, you must give it exactly the same punctuation. Even knowing you became an expert in this subject and that you will finish it faster. Finishing it faster means you have improved your velocity and, therefore, you are getting better and better in what you do.
So, whenever you are using points, avoid the word estimation. This word gives to people an incorrect impression while punctuating.
Please, leave your comments about this subject. I love to hear other people opinions.
Thanks for reading.
domingo, 14 de julho de 2013
Fixing Run-Jetty-Run Eclipse Plugin to Run Websockets
Run-Jetty-Run is an Eclipse plugin for running and debugging web apps using Jetty container. Although it has been a great and useful tool in the past days, lately, when I was playing around with websockets, I’ve found it was not working properly as it should.
It is important to say that the current stable build of Run-Jetty-Run plugin does not support the latest Jetty version (i.e. 9.0.4), so it became necessary to get its nightly build. Once I downloaded it, I've noticed it was not up-to-date either. Actually the last nightly build is pretty old too (the build date is 01/02/2013) and, unfortunately, it only supports Jetty 9.0.0.M3.
So, If you are facing the below issue or if you are a curious person, I would suggest you to keep reading.
java.util.ServiceConfigurationError: org.eclipse.jetty.websocket.servlet.WebSocketServletFactory: Provider org.eclipse.jetty.websocket.server.WebSocketServerFactory not found
at java.util.ServiceLoader.fail(ServiceLoader.java:231)
at java.util.ServiceLoader.access$300(ServiceLoader.java:181)
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:365)
at java.util.ServiceLoader$1.next(ServiceLoader.java:445)
at org.eclipse.jetty.websocket.servlet.WebSocketServlet.init(WebSocketServlet.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:242)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:516)
at org.eclipse.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:398)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:642)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:445)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:138)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:564)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:213)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1054)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:372)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:175)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:988)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:136)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:410)
at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:245)
at org.eclipse.jetty.server.HttpConnection$1.run(HttpConnection.java:75)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:597)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:528)
at java.lang.Thread.run(Thread.java:722)
|
Once the Run-Jetty-Run team seems to not be working anymore and since there were some changes in the internal Jetty API, I’ve decided to fix it by myself and to post the result to make life simple for everyone trying to run websockets into Eclipse.
It is important to say that this fix was tested only in the Eclipse Kepler. So, in order to avoid other issues, ensure you have the latest version of Kepler IDE. After that, you can follow the following steps:
- First of all, you must install the core of the Run-Jetty-Run plugin.
- For that, go to Help -> Install New Software.
- Then, enter the http://run-jetty-run.googlecode.com/svn/trunk/updatesite-nightly URL and install the Run Jetty Run Feature (Required)
- Once the core plugin has being installed, you must install my customized support for running Jetty 9.0.4.
- Download the file RunJettyRun904_byRubbo_1.0.0.201306302028.jar
- Copy the downloaded jar into the /<YOU_ECLIPSE_KEPLER_HOME>/plugins
- And, restart the eclipse
- Finally, right click on your websocket app and choose RunAs -> Run Jetty
- In Jetty tab, select the following Jetty Version: Jetty 9.0.4.by.Rubbo
- In Jetty Classpath tab, add your project in the Custom Jetty Classpath
- It is important to say that this step is only necessary because there is another bug in the core plugin which I didn’t want to lose my time to fix.
- So, we are done!!
- Click in the Run button and have fun..
Hope I’ve helped to make your life simple. ;-)
Thanks for reading.
Assinar:
Postagens (Atom)