Featured FREE Whitepapers

What's New Here?

enterprise-java-logo

EasyCriteria – An easy way to use the JPA Criteria

Today we will see about this tool that make easier to use the JPA Criteria. The application that uses this library will be cleaner, easier to use and portable across the JPA implementations. At the end of this post you will find the source code to download. What is Criteria? Currently is the best solution to create dynamic queries. Imagine a page that allows the user to do several types of queries; the requested query could be by name, by age or with both. Take a look bellow in how the query would look like if we concatenate a String: EntityManager em = emf.createEntityManager(); String hql = "select p from Person p where 1=1 ";if(parameters[0].equals("name")){ hql += " and p.name = '" + values[0] + "'"; }if(parameters[1].equals("age")){ hql += " and p.age = " + values[1]; }TypedQuery<Person> query = em.createQuery(hql, Person.class);System.out.println(query.getResultList()); Notice that in the code above a String concatenation is made; remember that this practice is a bad and dangerous practice because it allows “SQL Injection” hacker attack. To avoid this attack we should use a query with parameters: EntityManager em = emf.createEntityManager(); String hql = "select p from Person p where 1=1 ";if(parameters.contains("name")){ hql += " and p.name = :name"; }if(parameters.contains("age")){ hql += " and p.age = :age"; }TypedQuery<Person> query = em.createQuery(hql, Person.class);if(parameters.contains("name")){ query.setParameter("name", values[0].toString()); }if(parameters.contains("age")){ query.setParameter("age", Integer.valueOf(values[1].toString())); }System.out.println(query.getResultList()); Notice that the SQL Injection problem were solved but now the code must check parameters to add it to the query and later to pass its values; the code needs of two “parameters searches” to complete the task. The Java/Oracle developers had the brilliant idea when they created the Criteria concept that is perfect to this kind of situation. Check bellow how the code would look like with the native JPA Criteria: EntityManager em = emf.createEntityManager(); CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Person> cq = cb.createQuery(Person.class); Root<Person> root = cq.from(Person.class); cq.select(root);if(parameters.contains("name")){ Path<String> name = root.get("name"); cq.where(cb.and(cb.equal(name, values[0]))); }if(parameters.contains("age")){ Path<Integer> name = root.get("age"); cq.where(cb.and(cb.equal(name, Integer.valueOf(values[1].toString())))); }TypedQuery<Person> query = em.createQuery(cq);System.out.println(query.getResultList()); Is possible to see that to pass the parameters values is easier. There is no need to concatenate the String or to check the parameters list values to populate the values. Unfortunately the Criteria API is to complex and verbose to the extreme. If you want to do only a “select p from Person p” you would need to create the criteria bellow: EntityManager em = emf.createEntityManager(); CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Person> cq = cb.createQuery(Person.class); Root<Person> root = cq.from(Person.class); cq.select(root);TypedQuery<Person> query = em.createQuery(cq); System.out.println(query.getResultList()); Is to much code to do something so easy, list all persons from a table. To avoid all this verbosity the Open Source project named EasyCriteria were created. If a developer uses the EasyCriteria the query above would look like bellow: EntityManager em = emf.createEntityManager(); EasyCriteria<Person> easyCriteria = EasyCriteriaFactory.createQueryCriteria(em, Person.class);if(parameters.contains("name")){ easyCriteria.whereEquals("name", values[0]); }if(parameters.contains("age")){ easyCriteria.whereEquals("age", values[1]); }System.out.println(easyCriteria.getResultList()); Notice that the all JPA verbosity is gone. Now it is possible to have a clean code, easier to create dynamic queries. About the code above is worth to talk about:Line 2: An instance of the EasyCriteria is created through a “factory”. This factory exists to do the abstraction of the every needed steep to create an object of the EasyCriteriaImp type. In the future verions new types of the EasyCriteria will be added, e.g. “Tuple”. Lines 5 and 9: It is easier to pass the parameters. To pass the parameters to compare values (“name = :name”) just use the equals method that take as first parameter the attribute name; the second parameter will be the value that will be equaled. Line 12: To run the query it will not be necessary to use the Query interface. The EasyCriteria itself takes this responsibility. It is possible to extract the query result through the EasyCriteria. There are two methods available to get the query result: EasyCriteria.getSingleResult(), EasyCriteria.getResultList().In the EasyCriteria web page it is available several code samples and the methods that can be used. Other advantage of the EasyCriteria is the ability to “link” all methods: easyCriteria.whereEquals("name", values[0]).whereEquals("age", values[1]).getResultList(); It is an light weight library because the only dependency is the JPA that the system will need to have. Attention: your application will need to have a JPA implementation up and running. This library was developed with JUnit and tested with Hibernate, OpenJPA and EclipseLink. The JUnit also uses the Cobertura framework to check if all code lines (or most of it) are covered by the tests, so far we got 100% of coverage.EasyCriteria still in Beta but the development team already got planed some releases and functionalities. Other EasyCriteria advantage is that your software code in no long “coupled” to any kind of JPA implementation. Today the Hibernate has a good criteria tool, but your code must stay “attached” to it. With the EasyCriteria you will be able to use any kind of JPA implementation. The proof of this decoupled library is that the EasyCriteria has been tested with 3 implementations quoted earlier. The EasyCriteria has the methods: in, like, empty and others. The developer will be able to do join (just simple joins without parameter), distinct or even order by all with Criteria. Here you will find the EasyCriteria to download and have access to all its documentation. Click here to download the source code of this post. I hope that this post/tool may help you. Reference: EasyCriteria – An easy way to use the JPA Criteria from our JCG partner Hebert Coelho at the uaiHebert blog....
apache-logo

Integrating Spring, Velocity and Tiles

I like Tiles and I heard a lot about Velocity. They seem to serve different purpose and reportedly are easily married together, so I decided to give it a shot and use them both in Spring web app. The integration actually took many hours and was a real rollercoaster during which I learned a lot about all three technologies. Hopefully this post can spare someone this fun and let them focus on business. Goals When I use tiles, I don’t like the default (?) approach of tiles.xml. I don’t want to put imports of JS & CSS, page title, navigation, body etc. each in its own file like in the snippet below, because that makes me switch between editor windows. <definition name='hello' template='/WEB-INF/templates/main.jsp'> <put-attribute name='title' value='Hello' type='string' /> <put-attribute name='head' value='/WEB-INF/templates/hello-js-and-css.jsp' /> <put-attribute name='nav' value='/WEB-INF/templates/hello-nav.jsp' /> <put-attribute name='body' value='/WEB-INF/templates/hello.jsp' /> </definition> Obviously I don’t want to put too much detail in tiles.xml, either. What I really like is having one file per page, assembling the template in one place, such as this piece of JSP: <tiles:insertTemplate template='template.jsp'> <tiles:putAttribute name='title' value='Hello' /> <tiles:putAttribute name='head'> <script type='text/javascript' src='/js/jQuery.js' /> <script type='text/javascript' src='/js/hello.js' /> </tiles:putAttribute> <tiles:putAttribute name='body'> <div>Hello, world!</div> </tiles:putAttribute> </tiles:insertTemplate> In Velocity, it’s supposed to look like this: #tiles_insertTemplate({'template': 'template.vm'}) #tiles_putAttribute({'name':'title', 'value': 'Hello'})#end #tiles_putAttribute({'name':'head'}) <script type='text/javascript' src='/js/jQuery.js' /> <script type='text/javascript' src='/js/hello.js' /> #end #tiles_putAttribute({'name':'body'}) <div>Hello, world!</div> #end #end However, the docs on integration are really intended for adding some Velocity support to your Tiles-based app, while I wanted quite the opposite: Use Tiles in my rich Velocity app, with full support for spring context, macros etc. Solution In short, what we’re going to do is:Use VelocityViewResolver to resolve and render pages Add support for Tiles macros to this Velocity rendering engine Extend the Tiles renderer with full support for Velocity, including Spring context, macros etc. Ultimately we’re going to make it use the original Velocity engine created by Spring.Full source code in form of a minimal, complete web app are at github. For details see below. Spring & Velocity -> Tiles For the first step, we define viewResolver and velocityConfig like this: @Bean public VelocityConfig velocityConfig() { VelocityConfigurer cfg = new VelocityConfigurer(); cfg.setResourceLoaderPath('/WEB-INF/velocity/'); cfg.setConfigLocation(context .getResource('/WEB-INF/velocity.properties')); return cfg; }@Bean public ViewResolver viewResolver() { VelocityViewResolver resolver = new VelocityViewResolver(); resolver.setViewClass(VelocityToolboxView.class); resolver.setSuffix('.vm'); return resolver; } It’s important that we use VelocityToolboxView there, otherwise the tiles directives won’t work. We also need to put the following in velocity.properties: userdirective=org.apache.tiles.velocity.template.AddAttributeDirective,\ org.apache.tiles.velocity.template.AddListAttributeDirective,\ org.apache.tiles.velocity.template.DefinitionDirective,\ org.apache.tiles.velocity.template.GetAsStringDirective,\ org.apache.tiles.velocity.template.ImportAttributeDirective,\ org.apache.tiles.velocity.template.InsertAttributeDirective,\ org.apache.tiles.velocity.template.InsertDefinitionDirective,\ org.apache.tiles.velocity.template.InsertTemplateDirective,\ org.apache.tiles.velocity.template.PutAttributeDirective,\ org.apache.tiles.velocity.template.PutListAttributeDirective This adds basic support for Tiles directives to Velocity, but it’s still useless because once Velocity hands rendering over to Tiles, Tiles is unable to render Velocity and would simply ignore it (rendering syntax of #directives to browser. Tiles -> Velocity We need to teach Tiles to use Velocity. For this we’re going to need a custom TilesInitializer: @Bean public TilesConfigurer tilesConfigurer() { TilesConfigurer cfg = new TilesConfigurer(); cfg.setTilesInitializer(new VelocityTilesInitializer(velocityConfig())); return cfg; }public class VelocityTilesInitializer extends DefaultTilesInitializer { private VelocityConfig velocityConfig;public VelocityTilesInitializer(VelocityConfig velocityConfig) { this.velocityConfig = velocityConfig; }@Override protected AbstractTilesContainerFactory createContainerFactory( TilesApplicationContext context) { return new BasicTilesContainerFactory() {@Override protected List<TilesRequestContextFactory> getTilesRequestContextFactoriesToBeChained( ChainedTilesRequestContextFactory parent) { List<TilesRequestContextFactory> factories = super .getTilesRequestContextFactoriesToBeChained(parent); registerRequestContextFactory( VelocityTilesRequestContextFactory.class.getName(), factories, parent); return factories; }@Override protected AttributeRenderer createTemplateAttributeRenderer( BasicRendererFactory rendererFactory, TilesApplicationContext applicationContext, TilesRequestContextFactory contextFactory, TilesContainer container, AttributeEvaluatorFactory attributeEvaluatorFactory) { ContextPassingVelocityAttributeRenderer var = new ContextPassingVelocityAttributeRenderer( velocityConfig.getVelocityEngine()); var.setApplicationContext(applicationContext); var.setRequestContextFactory(contextFactory); var.setAttributeEvaluatorFactory(attributeEvaluatorFactory); var.commit(); return var; } }; } } We’re almost there, but here’s a tricky bit. Normally in lines 31-32 you would put velocityAttributeRenderer. However, this renderer completely ignores the Spring-augmented Velocity context & engine that Tiles received from Velocity. It creates its own VelocityEngine and lets it do the rendering, throwing away all the Spring and tiles directives and context objects. There is no way to change this behavior in Tiles (which otherwise seems to be an interesting study in design patterns and extensibility). I even created two JIRA issues for it: 541 for forwarding context and 542 for injecting VelocityEngine. Meanwhile, we have to make do with this workaround (see github for full source): public class ContextPassingVelocityAttributeRenderer extends AbstractTypeDetectingAttributeRenderer { // ...private VelocityEngine engine;public ContextPassingVelocityAttributeRenderer(VelocityEngine engine) { this.engine = engine; }// ...public void commit() { velocityView = new VelocityView(new TilesApplicationContextJeeConfig()); velocityView.setVelocityEngine(engine); }@Override public void write(Object value, Attribute attribute, TilesRequestContext request) throws IOException { if (value != null) { if (value instanceof String) { InternalContextAdapter adapter = (InternalContextAdapter) ((VelocityTilesRequestContext) request) .getRequestObjects()[0]; Context context = adapter.getInternalUserContext(); Template template = velocityView.getTemplate((String) value); velocityView.merge(template, context, request.getWriter()); } else { throw new InvalidTemplateException( 'Cannot render a template that is not a string: ' + value.toString()); } } else { throw new InvalidTemplateException('Cannot render a null template'); } }// ... It works arounds both of the JIRA issues and lets us accomplish the ultimate goal:The VelocityEngine injected to VelocityView here is the original VelocityEngine from Spring. Among other things, it supports Spring directives and context-dependent tools. The TilesRequestContext in write method still contains the original Velocity context created from Spring scaffolding. Standard implementation of VelocityAttributeRenderer simply throws it away. This workaround above extracts the original context and uses it for rendering.Conclusion This journey took much more time than I thought. Documentation on such cases is nonexistent, so I spent hours debugging, reading source code, experimenting, praying and cursing. It was even more fun as I had close to zero knowledge of internals of Spring view resolution and rendering engine, as well as Tiles and Velocity. It’s quite satisfying since I learned a ton about all those technologies and eventually was able to resolve it in a fairly elegant way. But it was also a frustrating and time-consuming riddle and I hope this post spares someone some trouble. Update – Velocity Tools A while later I discovered this solution does not support Velocity Tools property. Here’s how to add it: Spring & Velocity Tools. Reference: Integrating Spring, Velocity and Tiles from our JCG partner Konrad Garus at the Squirrel’s blog....
spring-logo

Java EE 6 VS Spring 3 : Java EE has killed Spring? No way!

Introduction Few days ago, I was listening to the epsiode 85 of the Java Spotlight Podcast. In this epsiode, Bert Ertman and Paul Bakker were talking about migrating from Spring to Java EE. Basically, in their introduction they were saying that, nowaday, there is no point choosing Spring over Java EE. We can read in their article : It took a while but Java EE has finally made the leap to be a standard, lightweight, fitting solutions to the vast majority of real-world development challenges in the mainstream enterprise applications space. You should have no single reason beyond choosing the standard. Over the last couple of months, I have seen a lot of blog articles with similar thoughts. Some are praisising Java EE, which is a good thing, while others are just denigrating Spring. This is the case of the article of Arun Gupta. My first thought on this article was “Oracle might be really desperate to write such trolls…”. I am not at all a Spring evangelist nor a Java EE hater. At the contrary, I have used intensively Java EE 5 for 2 years and am really happy to see that Java EE finally became a good competitor for Spring. My goal is not to praise Spring here, just to balance the words of the “Spring’s hater”. Standard VS Single vendor solution Is that good to have standards? Do you know this sentence “Responding to change over following a plan”? Yes, it is one the Agile rules. Of course it is a good thing to have standards, it is more than good, it is fundamental! But it comes with its drawbacks. If one day you have a problem with the standard, something not covered by the standard, your only solution is to fill an issue, cross your finger and wait 3 years… Are Spring and standards incompatible? Not at all! That is one of the reason I do not understand the “It is standard” argument. Spring does its best to provide the use of the standard. You are free to use JPA, the CDI annotation etc. I consider Spring more like an integration platform that let you use all Java EE technologies and also some additional features provided by Spring itself. Do I depend on SpringSource? Not really… What happen if tomorrow SpringSource stop developing Spring? I will continue using it… Spring Framework is under Apache 2.0 license, no doubt that the community will take the relay and that some new companies will offer support for Spring. Even if nobody do that, I am happy with Spring Framework in its current state, why would I change? Maybe I will reconsider it in 3 years, when a new version of Java EE will be released… What happen if tomorrow I am not happy with Spring Framework? The same thing than if I am not happy with Java EE… I stop using it… What happen if tomorrow I am not happy with my application server? The same thing than if I am not happy with Java EE… I change it… Except that, with Spring, I will have more choices (since Spring works with all Java EE application server + the others like tomcat, jetty etc…). Spring has always been innovative and will always be I will never forget that Spring has made CDI possible and easy for the Java web development. Java EE has followed (again 3 years later…) with the JSR-299. Spring is also currently providing some awesome solutions not provided at all by JavaEE:Spring Data (Really nice especially for the NoSQL world) Spring Social (Woops… JSR-357 has recently been rejected…) Spring Mobile …Some of them are in the plan of the next versions of Java EE (yay, we will have it in 3 years!) while others have still not been taken into consideration or have been rejected. Integration Testing One of the common argument for Java is that you don’t have to use mocks, you can do in-container testing thanks to Arquillian. I am definitely in favor of in-container testing instead of mocks and Arquillian is a great tool. Anyway, Arquillian is nice for Java EE but it is not Java EE! There is no standards for that and so you depend on a single vendor, JBoss (redhat), which makes the “It is standard” argument pointless. Then it is not impossible to test spring with Arquillian… At least, even if it is not perfect, Spring has the merit to provide something by its own… Conclusion I have not focused my article on the enhancement provided by the Java EE platform nor on the different features implemented by each, that was not my goal. I still believe that Java EE is a really good product and that it has finally become a serious competitor. But when I read “While Spring was revolutionary in its time [...], it really is last generation’s framework – some people are even calling it legacy” that really annoys me. How can we say that?! Maybe just to do a buzz… and it works! Reference: Java EE 6 VS Spring 3 : Java EE has killed Spring? No way! from our JCG partner Tibo Delor at the InvalidCodeException blog....
agile-logo

Looking For Leaders In All The Wrong Places

When I was a young developer, there was a re-org in the company. I found myself a team leader. That is the normal thing in software organizations (and I assume also in others) – you get a promotion because you’re competent enough in your current job. It’s not stupid (although many times with disastrous results), just normal. What made me a team leader was my track record as a developer. It seemed obvious that I could lead other developers to the same results. Obviously not. I was a lousy team leader.There are so many books about leadership. How to become a leader, what it takes to lead. But we’re so enamored with the star power of the leader, we forget something. There are no leaders without followers We really have a hard time to describe why we follow someone. Why we find time to listen to her, or read her blog, while dismiss others. Why we roll our eyes when the team leader says something, while the other team lead makes sense. Or even decide to give up qualities of life by voting for official positions. If you break it down, it’s comes down to basic human feelings. Our leaders help us feel safer and better about ourselves. So we seek their company, and we’re willing to do things for them. When they say something we believe in, we feel better we’re not alone. When they say something funny, we smile. When they blog about something interesting, we think we can someday become as smart as them. Followers create leaders, leaders don’t create themselves. Leaders vs Managers Most of the organizational pyramid is made of managers. Some have the ability to inspire people to achieve results (or in other words, make us feel better). We call them leaders. We’ll do a lot for them. We call the others managers. For them, we’ll do just enough to keep our pay. Why are there not enough leaders? Much like in politics, this isn’t the right question… Why aren’t there enough good managers? Those that make us feel better, give us autonomy to solve problems our way, the option to experiment and fail safely? Simple: the pyramid system does not reward it. If managers are punished for failures (getting bad reviews, not getting promoted, or fired) they won’t take risks, and therefore will not give their teams freedom. If they are constantly compared to their peers, they will not make the team feel better, but be worried about how they look instead. Stop looking for leaders Pyramids are a geometric marvel. The structure enforces stability. I’m not calling to flatten pyramids, I’m aware that it’s not that easy, and frankly, not my goal. The goal is better organizational results. We get these by better management. We can become better managers. When we do, then we start making changes in the organizations. Then we lead. Reference: Looking For Leaders In All The Wrong Places from our JCG partner Gil Zilberfeld at the Geek Out of Water blog....
java-logo

Solve design problems using Factory Pattern

Factory design pattern is one of the most commonly used patterns in object oriented environment. It is again from the Creational Design pattern category i.e. all about object creation. There are certain cases where the object creation is complex and might require some level of abstraction so that the client code is unaware of these complexities and internal implementation details. There might be scenarios where object creation is scattered and repetitive in various parts of the code.The Factory pattern resolves these issues by defining an interface which specifically creates the object but gives the flexibility to the implementation classes to decide on which class to instantiate.Definition:The Factory method pattern is to define an interface for creating objects but delegates the object creation to the subclasses.Objective: Looking at the problem statement the objective should be:Client should be unaware of the object instantiation Client should access the objects through a common interface.Do you know?Factory method design pattern is commonly used in various frameworks such as Struts, Spring, Apache in conjunction with decorator design pattern. There are various J2EE patterns which are based on this Factory pattern e.g. DAO pattern.Which principle of Object Oriented Design is used in Factory pattern? Encapsulation : because it encapsulates the creation code from the client. And obviously you can then think that the benefits of encapsulation are also applicable for this pattern like loose coupling and cohesion. Practical Example: Consider a Garment Factory which produces various types of garments like shirt, trousers. The consumers can request for the required types of garments through the factory. However from consumer’s perspective they are completely unaware of who is creating this object. They just know that the Factory is providing them the required garments. Problem Statement: It is a standard practice that objects are created by calling the “new” keyword. Imagine a scenario that there are multiple cases in the client class and we call multiple new keywords for creating new objects. if (selection.equalsIgnoreCase("Trouser")) { return new Trouser(); } else if (selection.equalsIgnoreCase("Shirt")) { return new Shirt(); } If we now have to add jacket or sweater we have to keep on modifying the client code and further add the new keyword. This creates a dependency on the client code and in turn makes it difficult to maintain. Another problem is that the client application has to know how many types of concrete classes are available upfront. Later if we have to add another concrete class e.g. sweater or jacket then client code has to be changed and recompiled. Solution: To resolve above problems factory pattern can be used explicitly.The first problem of accessing too many new keyword can be resolved by using a Factory class.The second problem can be solved by using an interface which the concrete classes will implement and the client will always point to the interface class rather than the concrete classes. So in this way client will be completely unaware of various types of concrete classes which will be required.What is an interface?An Interfacein Java is a collection of method definitions without implementation. The class which implements the interface has to provides the implementation and must implement all the methods described in the interface. The interface is a contract which tells the classes what to be done leaves it for the classes to decide on how they can be implemented. interface Bounceable { void setBounce(); }The below class diagram will give a complete overview of implementation of Factory Pattern:Factory Pattern Class DiagramLet’s take a look at the sample code to implement the Factory Pattern:GarmentType.javapublic interface GarmentType { String print(); }Trouser.javapublic class Trouser implements GarmentType { @Override public String print() { System.out.println("Trouser Created"); return "Trouser"; }}Shirt.javapublic class Shirt implements GarmentType { @Override public String print() { System.out.println("Shirt Created"); return "Shirt"; } }GarmentFactory.javapublic class GarmentFactory { public static GarmentType createGarments(String selection) { if (selection.equalsIgnoreCase("Trouser")) { return new Trouser(); } else if (selection.equalsIgnoreCase("Shirt")) { return new Shirt(); } throw new IllegalArgumentException("Selection doesnot exist"); } }Client.javapublic class Client { public static void main(String[] args) { System.out.println("Enter your selection:"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String selection = null; try { selection = br.readLine(); } catch (IOException e) { e.printStackTrace(); } GarmentType objGarmentType = GarmentFactory.createGarments(selection); System.out.println(objGarmentType.print()); } }Advantage of Factory Pattern: a)This client does not need to know about the subclass of objects which requires to be created. It requires the reference to the interface and the factory object. b)The object creation processes are taken away from the client to the factory and thereby decoupling the client code with the object creation code. This in turn will help in reusability as this code can be used by other clients. c)The Factory pattern also helps in the scalability of the application as the client code only refers to the interface and we can add more products implementing the interface without making many changes in the client code. d)Code maintainability is a beneficial if the application uses Factory pattern as the object creation is centralized. Reference: Solve design problems using Factory Pattern from our JCG partner Mainak Goswami at the Idiotechie blog....
google-analytics-logo

Google API: How to access Analytics data?

Before we dig into Google Analytics API it is always useful to understand few of the Google Analytics jargon and their relationship . Google Account: To access Google Analytics the user will need a Google Account which enables users to login to multiple Google products e.g. Gmail, Blogger, Analytics, Adsense etc. [user.01@gmail.com]. Google Analytics Account:When the user wants to access the features of the web analytics they will need to register for this service. This is a unique ID representing the analytics account. The user can still use their Google account email address to authenticate and login to the Analytics account services. [e.g. 65421]Google Analytics Sample AccountWeb properties: A web property can be referred to as one website which can be tracked independently. If the account is called AbcCompany then a web property can be abc.com which refers to the user’s personal website, another web property can be abcbiz.com which refers to user’s business website and other one can be abc.mobi which is specifically targeted to his mobile customers. The web properties under the account will have the same Account number but with different suffix. E.g. If the Account Id for AbcCompany is 65421 so the web property for abc.com can be UA-65421-1, for abcbiz.com it can be UA-65421-2.Google Analytics sample propertyCreate a New Property using the Property tab:Create a New PropertyGoogle Analytics Profile: Each web property account will have at least one analytics profile. The profile has access to all the analytics data and reports. Each profile will have a unique profile Id. The profiles can have multiple Goals, Users, Filters and Assets.ProfilesThe Profile settings tab gives the details of the Profile Id and Website URL.The profile can have one or multiple users.Edit Profile SettingsThe details of the relationship is highlighted in the below diagram.GA User Profile Account relationshipWhat is OAuth 2.0? OAuth is an open standard for authorisation. It allows users to share their resources from one location to another location without the necessity to share credentials. OAuth 2.0 is based on the OAuth protocol however it helps with new authentication features for web applications, desktop applications, mobile applications etc. They use tokens instead of the actual username and password for speaking to each other and provide authorisation. How is Google API related to OAuth2.0? Google API provides access to their application using OAuth 2.0 standard. Google uses this protocol as their authentication and authorization especially when the third party clients want to have an access to the Google application data securely. The Google authorisation works in few high level steps: a) Register application with Google b) Redirect a browser to the URL c) Parse a token from the response d) Send the token to the Google Authorisation server. e) Get the Google Analytics data by using the access token to the request. The following diagram describes the steps which are followed to get authenticated and authorized to the Google Server (in this case Analytics server).Google Analytics ArchitectureWell all the introduction is now over. We will be back to action. Till now we have learnt about the various features of Google Analytics data and also about the authorisation and authentication mechanism. Now we will go into the implementation details. Oops…There is still one item missing. It’s all about what data we will be accessing from Google Analytics and how are they related. Dimension vs MetricsDimension vs MetricsIn simple terms the Dimension in Google analytics represents the rows in the report and metrics represents the columns. E.g. the Dimension refers to Country, Browsers, Traffic sources and metrics refers the visits, new visitors, transactions etc. So what are we trying to do with all these details? Problem Statement: We are trying to create a standalone application which will try to use the OAuth 2.0 protocol and fetch the data from the Google Analytics. Solution: Step 1: Download and Import Jar files To start with we will need to download and import the following jar files: Download Location : Google client APIgoogle-api-client-1.8.0-beta.jar – Contains the Core API code for the Google Analyticsgoogle-oauth-client-1.8.0-beta.jar – Contains the OAuth client codegson-2.1.jar – Java library to convert JSON to Java object and vice versaguava-11.0.1.jar – This jar contains several Google’s core libraries e.g. collections, caching, primitive support, common annotations, string processingjackson-core-asl-1.9.4.jar – This is high performance JSON processorStep 2: Register client application with Google Every application has to be registered with the Google API so that we can use the OAuth 2.0 token during the authentication and authorisation process. To register an application the user has to login to the Google account and go to Google API console. In the Google API console Create a New Project using the left hand menu.Create a New projectUsing the Services tab enable the Analytics API so that it can be accessed.Enable Analytics APIFrom the API Access tab create an OAuth 2.0 client ID.Create OAuth client IDCreate Branding information for Client IDCreate Branding informationSelect application type. In our example we select “Installed application” usually running on the local system.Select Application TypeAPI console summary providing the details of the Client ID and Client secret.Google API Console SummaryStep 3: Authorising Requests The registration gives the clientId and clientSecret value for your application so that it can work with the Google API. This is keys will avoid the client application to share the username or password and instead make use of these keys. When the client application is executed it prompts the users to allow access and redirects the users to the Google URL which in turns provides an authorisation code. The authorisation code is fed back to the client application which then uses the code to get the access token. Step 4: Accessing the Google Analytics user data The client application uses the access token to get the Google analytics user’s data. <<GA Example Download Code>> Sample Code Explanation:The Client ID and Client Secret value received from the Google API console needs to copied here in the program. private static final String CLIENT_ID = "XXXXXXXXXX"; private static final String CLIENT_SECRET = "XXXXXXXXX"; Generate the URL which will be used to get the authorisation code. String authorizationUrl = new GoogleAuthorizationRequestUrl(CLIENT_ID, REDIRECT_URL, SCOPE).build(); Here REDIRECT_URL refers to the absolute URI path which the authorisation server will redirect the user agent to the end user authorisation step is complete and SCOPE refers to the scope of the access request expressed. Once the application is executed the URL is generated. This URL will ask if the Analytics account user can allow the access to get the authorisation code. Once the authorisation code is generated it will be used in the client application to get an access to the Google API token. Read the authorisation code from console: BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); Get an access to the OAuth 2.0 token using the authorisation code: AccessTokenResponse response = new GoogleAccessTokenRequest.GoogleAuthorizationCodeGrant( netHttpTransport, jacksonFactory, CLIENT_ID, CLIENT_SECRET, authorizationCode, REDIRECT_URL).execute(); Initialize the Analytics service object: Analytics analytics = Analytics.builder(netHttpTransport, jacksonFactory) .setHttpRequestInitializer(googleAccessProtectedResource) .setApplicationName(APPLICATION_NAME).build(); Get Profile details: Profiles profiles = analytics.management().profiles() .list("~all", "~all").execute(); Get Analytics data using API query: Get apiQuery = analytics.data().ga() .get("ga:" + profile.getId(), // Table ID ="ga"+ProfileID "2012-03-21", // Start date "2012-05-04", // End date "ga:visits"); // Metrics Set filters: apiQuery.setFilters("ga:medium==referral"); apiQuery.setMaxResults(100); Execute query: GaData gaData = apiQuery.execute(); The data can then be retrieved from the GaData object using the retrieveData() method. public static void retrieveData(GaData gaData) { // Get Row Data if (gaData.getTotalResults() > 0) { // Get the column headers for (ColumnHeaders header : gaData.getColumnHeaders()) { System.out.format("%-20s", header.getName() + '(' + header.getDataType() + ')'); } System.out.println(); // Print the rows of data. for (List<String> rowValues : gaData.getRows()) { for (String value : rowValues) { System.out.format("%-20s", value); } System.out.println(); } } else { System.out.println("No data available"); } } In case you want to know more about Google Analytics then you can refer to our article “All about Google Analytics“. Reference: Google API: How to access Analytics data? from our JCG partner Mainak Goswami at the Idiotechie blog....
java-duke-logo

RichText editor component for SWT based applications

This article will go through the task of implementing our own RichText editor component with SWT. I faced the need for such a visual component when developing a desktop based application for one of my customers and wanted to add a functionality to allow users to write rich text comments with bold, italic, strike through, etc. capabilities. At that moment I started to research the web in order to find an open source library that could save me from the work of rolling it out from scratch and I came across this list of “already done” implementations.Let’s list here the needs I had for that kind of component:It should be a native SWT component, not an Eclipse View or Editor and it must be embeddable in any SWT composite. It should allow basic formatting as bolds, italics, strike through, etc. It should support basic clipboard operations as copy, cut and paste. It should output the text using basic HTML. It needs to be able to parse the basic HTML generated in order to allow editions.So, most of the solutions I found didn’t fit my needs as they were either Eclipse Views/Editors, too cumbersome to integrate, tried to achieve too much functionality or didn’t align with the icon set I was using to brand my business application (this is a minor issue though but summing it all up it added more reasons for my decision). So at the end I finally decided to write it from scratch based in the StyledText SWT standard component and using this example as a starting point.The RichText controlAllmost all the work will be performed by the RichText control itself. I will add some support classes that will act as helpers to format the resulting text to basic HTML and as providers of images, localised strings and so on. import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List;import javax.xml.parsers.ParserConfigurationException;import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CaretListener; import org.eclipse.swt.custom.ExtendedModifyEvent; import org.eclipse.swt.custom.ExtendedModifyListener; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.custom.VerifyKeyListener; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Caret; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.xml.sax.SAXException;public class RichText extends Composite {private List cachedStyles = Collections.synchronizedList(new LinkedList());private ToolBar toolBar; private StyledText styledText;private ToolItem boldBtn; private ToolItem italicBtn; private ToolItem strikeThroughBtn; private ToolItem underlineBtn;private ToolItem pasteBtn; private ToolItem eraserBtn;public RichText(Composite parent, int style) { super(parent, style); initComponents(); }public void addCaretListener(CaretListener listener) { styledText.addCaretListener(listener); }public void removeCaretListener(CaretListener listener) { styledText.removeCaretListener(listener); }public void addExtendedModifyListener(ExtendedModifyListener listener) { styledText.addExtendedModifyListener(listener); }public void removeExtendedModifyListener(ExtendedModifyListener listener) { styledText.removeExtendedModifyListener(listener); }public void addModifyListener(ModifyListener listener) { styledText.addModifyListener(listener); }public void removeModifyListener(ModifyListener listener) { styledText.removeModifyListener(listener); }public void addVerifyKeyListener(VerifyKeyListener listener) { styledText.addVerifyKeyListener(listener); }public void removeVerifyKeyListener(VerifyKeyListener listener) { styledText.removeVerifyKeyListener(listener); }public void addVerifyListener(VerifyListener listener) { styledText.addVerifyListener(listener); }public void removeVerifyListener(VerifyListener listener) { styledText.removeVerifyListener(listener); }public int getCharCount() { return styledText.getCharCount(); }public Caret getCaret() { return styledText.getCaret(); }public int getCaretOffset() { return styledText.getCaretOffset(); }/** * Obtain an HTML formatted text from the component contents * * @return an HTML formatted text */ public String getFormattedText() { String plainText = styledText.getText();RichStringBuilder builder = new RichStringBuilder(); Integer[] lineBreaks = getLineBreaks();int brIdx = 0; int start = 0; int end = (lineBreaks.length > brIdx ? lineBreaks[brIdx++] : plainText.length() - 1);while (start < end) { builder.startParagraph(); StyleRange[] ranges = styledText.getStyleRanges(start, (end - start)); if (ranges != null && ranges.length > 0) { for (int i = 0;i < ranges.length;i++) { if (start < ranges[i].start) { builder.append(plainText.substring(start, ranges[i].start)); }List styles = translateStyle(ranges[i]); builder.startFontStyles(styles.toArray(new FontStyle[styles.size()])); builder.append(plainText.substring(ranges[i].start, ranges[i].start + ranges[i].length)); builder.endFontStyles(styles.size());start = (ranges[i].start + ranges[i].length) + 1; } } if (start < end) { builder.append(plainText.substring(start, end)); } start = end + styledText.getLineDelimiter().length(); end = (lineBreaks.length > brIdx ? lineBreaks[brIdx++] : plainText.length() - 1); builder.endParagraph(); }return builder.toString(); }public void setFormattedText(String text) throws ParserConfigurationException, SAXException, IOException { RichTextParser parser = RichTextParser.parse(text); styledText.setText(parser.getText()); styledText.setStyleRanges(parser.getStyleRanges()); }public int getLineAtOffset(int offset) { return styledText.getLineAtOffset(offset); }public int getLineCount() { return styledText.getLineCount(); }public int getLineSpacing() { return styledText.getLineSpacing(); }public String getText() { return styledText.getText(); }protected void applyFontStyleToSelection(FontStyle style) { Point sel = styledText.getSelectionRange(); if ((sel == null) || (sel.y == 0)) { return ; }StyleRange newStyle; for (int i = sel.x; i < (sel.x + sel.y); i++) { StyleRange range = styledText.getStyleRangeAtOffset(i); if (range != null) { newStyle = (StyleRange) range.clone(); newStyle.start = i; newStyle.length = 1; } else { newStyle = new StyleRange(i, 1, null, null, SWT.NORMAL); }switch (style) { case BOLD: newStyle.fontStyle ^= SWT.BOLD; break; case ITALIC: newStyle.fontStyle ^= SWT.ITALIC; break; case STRIKE_THROUGH: newStyle.strikeout = !newStyle.strikeout; break; case UNDERLINE: newStyle.underline = !newStyle.underline; break; }styledText.setStyleRange(newStyle); }styledText.setSelectionRange(sel.x + sel.y, 0); }/** * Clear all styled data */ protected void clearStylesFromSelection() { Point sel = styledText.getSelectionRange(); if ((sel != null) && (sel.y != 0)) { StyleRange style = new StyleRange( sel.x, sel.y, null, null, SWT.NORMAL); styledText.setStyleRange(style); } styledText.setSelectionRange(sel.x + sel.y, 0); }private Integer[] getLineBreaks() { List list = new ArrayList(); int lastIdx = 0; while (lastIdx < styledText.getCharCount()) { int br = styledText.getText().indexOf( styledText.getLineDelimiter(), lastIdx); if (br >= lastIdx && !list.contains(br)) { list.add(br); } lastIdx += styledText.getLineDelimiter().length() + 1; } Collections.sort(list); return list.toArray(new Integer[list.size()]); }protected void handleCutCopy() { // Save the cut/copied style info so that during paste we will maintain // the style information. Cut/copied text is put in the clipboard in // RTF format, but is not pasted in RTF format. The other way to // handle the pasting of styles would be to access the Clipboard // directly and // parse the RTF text. cachedStyles = Collections .synchronizedList(new LinkedList()); Point sel = styledText.getSelectionRange(); int startX = sel.x; for (int i = sel.x; i <= sel.x + sel.y - 1; i++) { StyleRange style = styledText.getStyleRangeAtOffset(i); if (style != null) { style.start = style.start - startX; if (!cachedStyles.isEmpty()) { StyleRange lastStyle = cachedStyles .get(cachedStyles.size() - 1); if (lastStyle.similarTo(style) && lastStyle.start + lastStyle.length == style.start) { lastStyle.length++; } else { cachedStyles.add(style); } } else { cachedStyles.add(style); } } } pasteBtn.setEnabled(true); }private void handleExtendedModified(ExtendedModifyEvent event) { if (event.length == 0) return;StyleRange style; if (event.length == 1 || styledText.getTextRange(event.start, event.length).equals( styledText.getLineDelimiter())) { // Have the new text take on the style of the text to its right // (during // typing) if no style information is active. int caretOffset = styledText.getCaretOffset(); style = null; if (caretOffset < styledText.getCharCount()) style = styledText.getStyleRangeAtOffset(caretOffset); if (style != null) { style = (StyleRange) style.clone(); style.start = event.start; style.length = event.length; } else { style = new StyleRange(event.start, event.length, null, null, SWT.NORMAL); } if (boldBtn.getSelection()) style.fontStyle |= SWT.BOLD; if (italicBtn.getSelection()) style.fontStyle |= SWT.ITALIC; style.underline = underlineBtn.getSelection(); style.strikeout = strikeThroughBtn.getSelection(); if (!style.isUnstyled()) styledText.setStyleRange(style); } else { // paste occurring, have text take on the styles it had when it was // cut/copied for (int i = 0; i < cachedStyles.size(); i++) { style = cachedStyles.get(i); StyleRange newStyle = (StyleRange) style.clone(); newStyle.start = style.start + event.start; styledText.setStyleRange(newStyle); } } }private void handleTextSelected(SelectionEvent event) { Point sel = styledText.getSelectionRange(); if ((sel != null) && (sel.y != 0)) { StyleRange[] styles = styledText.getStyleRanges(sel.x, sel.y); eraserBtn.setEnabled((styles != null) && (styles.length > 0)); } else { eraserBtn.setEnabled(false); } }private void handleKeyReleased(KeyEvent event) { if ((event.keyCode == SWT.ARROW_LEFT) || (event.keyCode == SWT.ARROW_UP) || (event.keyCode == SWT.ARROW_RIGHT) || (event.keyCode == SWT.ARROW_DOWN)) { updateStyleButtons(); } }private void updateStyleButtons() { int caretOffset = styledText.getCaretOffset(); StyleRange style = null; if (caretOffset >= 0 && caretOffset < styledText.getCharCount()) { style = styledText.getStyleRangeAtOffset(caretOffset); }if (style != null) { boldBtn.setSelection((style.fontStyle & SWT.BOLD) != 0); italicBtn.setSelection((style.fontStyle & SWT.ITALIC) != 0); underlineBtn.setSelection(style.underline); strikeThroughBtn.setSelection(style.strikeout); } else { boldBtn.setSelection(false); italicBtn.setSelection(false); underlineBtn.setSelection(false); strikeThroughBtn.setSelection(false); } }private void initComponents() { GridLayout layout = new GridLayout(); layout.numColumns = 1; setLayout(layout);toolBar = createToolBar(this); toolBar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));styledText = new StyledText(this, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL); styledText.setLayoutData(new GridData(GridData.FILL_BOTH)); styledText.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { handleKeyReleased(e); } }); styledText.addExtendedModifyListener(new ExtendedModifyListener() { @Override public void modifyText(ExtendedModifyEvent event) { handleExtendedModified(event); } }); styledText.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { updateStyleButtons(); } }); styledText.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { handleTextSelected(event); } }); }private ToolBar createToolBar(Composite parent) { ToolBar toolBar = new ToolBar(parent, SWT.FLAT);boldBtn = new ToolItem(toolBar, SWT.CHECK); boldBtn.setImage(RichTextImages.IMG_BOLD); boldBtn.setToolTipText(RichTextStrings.boldBtn_tooltipText); boldBtn.addSelectionListener( new FontStyleButtonListener(FontStyle.BOLD));italicBtn = new ToolItem(toolBar, SWT.CHECK); italicBtn.setImage(RichTextImages.IMG_ITALIC); italicBtn.setToolTipText(RichTextStrings.italicBtn_tooltipText); italicBtn.addSelectionListener( new FontStyleButtonListener(FontStyle.ITALIC));underlineBtn = new ToolItem(toolBar, SWT.CHECK); underlineBtn.setImage(RichTextImages.IMG_UNDERLINE); underlineBtn.setToolTipText(RichTextStrings.underlineBtn_tooltipText); underlineBtn.addSelectionListener( new FontStyleButtonListener(FontStyle.UNDERLINE));strikeThroughBtn = new ToolItem(toolBar, SWT.CHECK); strikeThroughBtn.setImage(RichTextImages.IMG_STRIKE_THROUGH); strikeThroughBtn.setToolTipText(RichTextStrings.strikeThroughBtn_tooltipText); strikeThroughBtn.addSelectionListener( new FontStyleButtonListener(FontStyle.STRIKE_THROUGH));new ToolItem(toolBar, SWT.SEPARATOR);ToolItem cutBtn = new ToolItem(toolBar, SWT.PUSH); cutBtn.setImage(RichTextImages.IMG_CUT); cutBtn.setToolTipText(RichTextStrings.cutBtn_tooltipText); cutBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleCutCopy(); styledText.cut(); } });ToolItem copyBtn = new ToolItem(toolBar, SWT.PUSH); copyBtn.setImage(RichTextImages.IMG_COPY); copyBtn.setToolTipText(RichTextStrings.copyBtn_tooltipText); copyBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleCutCopy(); styledText.copy(); } });pasteBtn = new ToolItem(toolBar, SWT.PUSH); pasteBtn.setEnabled(false); pasteBtn.setImage(RichTextImages.IMG_PASTE); pasteBtn.setToolTipText(RichTextStrings.pasteBtn_tooltipText); pasteBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { styledText.paste(); } });new ToolItem(toolBar, SWT.SEPARATOR);eraserBtn = new ToolItem(toolBar, SWT.PUSH); eraserBtn.setEnabled(false); eraserBtn.setImage(RichTextImages.IMG_ERASER); eraserBtn.setToolTipText(RichTextStrings.eraserBtn_tooltipText); eraserBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { clearStylesFromSelection(); } });return toolBar; }private List translateStyle(StyleRange range) { List list = new ArrayList();if ((range.fontStyle & SWT.BOLD) != 0) { list.add(FontStyle.BOLD); } if ((range.fontStyle & SWT.ITALIC) != 0) { list.add(FontStyle.ITALIC); } if (range.strikeout) { list.add(FontStyle.STRIKE_THROUGH); } if (range.underline) { list.add(FontStyle.UNDERLINE); }return list; }private class FontStyleButtonListener extends SelectionAdapter { private FontStyle style;public FontStyleButtonListener(FontStyle style) { this.style = style; }@Override public void widgetSelected(SelectionEvent e) { applyFontStyleToSelection(style); } }}As you can see our RichText control is basically a wrapper around a ToolBar and a StyledText components with different event listeners hook both controls.  Support classesIn this section I will show the code I used to implement some of the support classes used by my rich text editor control. I will omit here the classes that provide my control with images and localised strings as there are too many examples out there about how to do it in SWT and I will focus on that classes I needed to format and parse the output/input of the control.The first of it is a Java enum that will be used to identify the different supported font styles: public enum FontStyle { BOLD, ITALIC, STRIKE_THROUGH, UNDERLINE }Next one is called RichStringBuilder and it will be used as a helper class to format the contents of the StyledText component into basic HTML: import java.util.Stack;public final class RichStringBuilder {public static final String LINE_DELIMITER = "<br/>";private StringBuilder builder; private Stack fontStyleStack;public RichStringBuilder() { builder = new StringBuilder(); fontStyleStack = new Stack(); }public RichStringBuilder append(String text) { builder.append(text); return this; }public RichStringBuilder appendLineBreak() { builder.append(LINE_DELIMITER); return this; }public RichStringBuilder startParagraph() { builder.append("<p>"); return this; }public RichStringBuilder startFontStyle(FontStyle fontStyle) { fontStyleStack.push(fontStyle); internalStartFontStyle(fontStyle); return this; }public RichStringBuilder startFontStyles(FontStyle... fontStyles) { for (FontStyle fs : fontStyles) { startFontStyle(fs); } return this; }public RichStringBuilder endFontStyles(int count) { for (int i = 0;i < count;i++) { endStyle(); } return this; }public RichStringBuilder endStyle() { if (fontStyleStack.size() > 0) { FontStyle style = fontStyleStack.pop(); internalEndFontStyle(style); } return this; }public RichStringBuilder endParagraph() { flushStyles(); builder.append("</p>"); return this; }public void flushStyles() { while (fontStyleStack.size() > 0) { endStyle(); } }@Override public boolean equals(Object o) { if (this == o) return true; if (null == o) return false; if (!(o instanceof RichStringBuilder)) return false;return ((RichStringBuilder) o).builder.equals(builder); }@Override public int hashCode() { return builder.hashCode(); }@Override public String toString() { return builder.toString(); }private void internalStartFontStyle(FontStyle fontStyle) { switch (fontStyle) { case BOLD: builder.append("<b>"); break; case ITALIC: builder.append("<i>"); break; case STRIKE_THROUGH: builder.append("<del>"); break; case UNDERLINE: builder.append("<ins>"); break; } }private void internalEndFontStyle(FontStyle fontStyle) { switch (fontStyle) { case BOLD: builder.append("</b>"); break; case ITALIC: builder.append("</i>"); break; case STRIKE_THROUGH: builder.append("</del>"); break; case UNDERLINE: builder.append("</ins>"); break; } }}And the third one is a SAX based content handler that will launch events when parsing basic HTML into the StyledText control: import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import java.util.Stack;import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory;import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler;public final class RichTextParser {public static RichTextParser parse(String formattedText) throws ParserConfigurationException, SAXException, IOException { return new RichTextParser(formattedText); }private StringBuilder text = new StringBuilder();private List styleRanges = new ArrayList();private RichTextParser(String formattedText) throws ParserConfigurationException, SAXException, IOException { StringReader reader = new StringReader(formattedText); SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); DefaultHandler handler = new RichTextContentHandler(); parser.parse(new InputSource(reader), handler); }public String getText() { return text.toString(); }public StyleRange[] getStyleRanges() { return styleRanges.toArray(new StyleRange[styleRanges.size()]); }private class RichTextContentHandler extends DefaultHandler {private Stack<List> stylesStack = new Stack<List>(); private String lastTextChunk = null;@Override public void characters(char[] ch, int start, int length) throws SAXException { lastTextChunk = new String(ch, start, length); }@Override public void endElement(String uri, String localName, String qName) throws SAXException { // If there is not any previous text chunk parsed then return if (lastTextChunk == null) return; // If the tag found is not a supported one then return if (!"p".equals(qName) || !"b".equals(qName) || !"i".equals(qName) || !"ins".equals(qName) || !"del".equals(qName)) { return; }List lastStyles = lastFontStyles(true); if (lastStyles != null) { StyleRange range = transform(lastStyles); range.start = currentIndex() + 1; range.length = lastTextChunk.length(); styleRanges.add(range); }text.append(lastTextChunk); lastTextChunk = null; }@Override public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { // If the tag found is not a supported one then return if (!"p".equals(qName) || !"b".equals(qName) || !"i".equals(qName) || !"ins".equals(qName) || !"del".equals(qName)) { return; }List lastStyles = lastFontStyles(false); if (lastTextChunk == null) { if (lastStyles == null) { lastStyles = new ArrayList(); stylesStack.add(lastStyles); } } else { if (lastStyles != null) { StyleRange range = transform(lastStyles); range.start = currentIndex() + 1; range.length = lastTextChunk.length(); styleRanges.add(range); }text.append(lastTextChunk); lastTextChunk = null; }if ("b".equals(qName)) { lastStyles.add(FontStyle.BOLD); } else if ("i".equals(qName)) { lastStyles.add(FontStyle.ITALIC); } else if ("ins".equals(qName)) { lastStyles.add(FontStyle.UNDERLINE); } else { lastStyles.add(FontStyle.STRIKE_THROUGH); } }private StyleRange transform(List styles) { StyleRange range = new StyleRange(); range.start = currentIndex() + 1; range.length = lastTextChunk.length(); for (FontStyle fs : styles) { if (FontStyle.BOLD == fs) { range.fontStyle = (range.fontStyle & SWT.BOLD); } else if (FontStyle.ITALIC == fs) { range.fontStyle = (range.fontStyle & SWT.ITALIC); } else if (FontStyle.STRIKE_THROUGH == fs) { range.strikeout = true; } else if (FontStyle.UNDERLINE == fs) { range.underline = true; } } return range; }private List lastFontStyles(boolean remove) { List lastStyles = null; if (stylesStack.size() > 0) { if (remove) { lastStyles = stylesStack.pop(); } else { lastStyles = stylesStack.peek(); } } return lastStyles; }private int currentIndex() { return text.length() - 1; }}}ConclusionImplementing your own SWT RichText control may not be the best option for your requirements, you will need to balance the pros and cons of doing so and whether it is worth to invest on one of the ready made commercial solutions out there. However, I want to demonstrate with this article doing your own (simple & lightweight) rich text editor embeddable in SWT dialogs and views it’s easy to accomplish and requires little effort compared to the benefits you obtain from that.Reference: RichText editor component for SWT based applications from our JCG partner Alonso Dominguez at the Code Nibbles blog....
apache-camel-logo

When to use Apache Camel?

Apache Camel is one of my favorite open source frameworks in the JVM / Java environment. It enables easy integration of different applications which use several protocols and technologies. This article shows when to use Apache Camel and when to use other alternatives. The Problem: Enterprise Application Integration (EAI) Enterprise application integration is necessary in almost every company due to new products and applications. Integrating these applications creates several problems. New paradigms come up every decade, for example client / server communication, Service-oriented Architecture (SOA) or Cloud Computing. Besides, different interfaces, protocols and technologies emerge. Instead of storing data in files in the past (many years ago), SQL databases are used often today. Sometimes, even NoSQL databases are required in some usecases. Synchronous remote procedure calls or asynchronous messaging is used to communicate via several technologies such as RMI, SOAP Web Services, REST or JMS. A lot of software silos exists. Nevertheless, all applications and products of these decades have to communicate with each other to work together perfectly. Enterprise Integration Patterns (EIP) Of course, you could reinvent the wheel for each problem, write some spaghetti code and let the applications work together. Unfortunately, your management will not like the long-term perspective of this solution. Enterprise Integration Patterns (www.eaipatterns.com) help to fragment problems and use standardized ways to integrate applications. Using these, you always use the same concepts to transform and route messages. Thus, it is a good idea to forget about reinventing the wheel each time you have a problem. Alternatives for integrating Systems Three alternatives exist for integrating applications. EIPs can be used in each solution. Solution 1: Own custom Solution Implement a individual solution that works for your problem without separating problems into little pieces. This works and is probably the fastest alternative for small use cases. You have to code all by yourself. Maintenance will probably be high if team members change. Solution 2: Integration Framework Use a framework which helps to integrate applications in a standardized way using several integration patterns. It reduces efforts a lot. Every developer will easily understand what you did (if he knows the used framework). Solution 3: Enterprise Service Bus (ESB) Use an enterprise service bus to integrate your applications. Under the hood, the ESB also uses an integration framework. But there is much more functionality, such as business process management, a registry or business activity monitoring. You can usually configure routing and such stuff within a graphical user interface – you have to decide at your own if that reduces complexity and efforts. Usually, an ESB is a complex product. The learning curve is much higher. But therefore you get a very powerful tool which should offer all your needs. What is Apache Camel? Apache Camel is a lightweight integration framework which implements all EIPs. Thus, you can easily integrate different applications using the required patterns. You can use Java, Spring XML, Scala or Groovy. Almost every technology you can imagine is available, for example HTTP, FTP, JMS, EJB, JPA, RMI, JMS, JMX, LDAP, Netty, and many, many more (of course most ESBs also offer support for them). Besides, own custom components can be created very easily. You can deploy Apache Camel as standalone application, in a web container (e.g. Tomcat or Jetty), in a JEE application Server (e.g. JBoss AS or WebSphere AS), in an OSGi environment or in combination with a Spring container. If you need more information about Apache Camel, please go to its web site as starting point: http://camel.apache.org. This article is no technical introduction J When to use Apache Camel? Apache Camel is awesome if you want to integrate several applications with different protocols and technologies. Why? There is one feature (besides supporting so many technologies and besides supporting different programming languages) which I really appreciate a lot: Every integration uses the same concepts! No matter which protocol you use. No matter which technology you use. No matter which domain specific language (DSL) you use – it can be Java, Scala, Groovy or Spring XML. You do it the same way. Always! There is a producer, there is a consumer, there are endpoints, there are EIPs, there are custom processors / beans (e.g. for custom transformation) and there are parameters (e.g. for credentials). Here is one example which contains all of these concepts using the Java DSL: from(„activeMQ:orderQueue“)..transaction().log(„processing order“).to(mock:“notYetExistingInterface“) Now let’s look at another example using the Scala DSL: „file:incomingOrders?noop=true“ process(new TransformationProcessor) to „jdbc:orderDatastore“ If you are a developer, you should be able to recognize what these routes do, don’t you? Two other very important features are the support for error-handling (e.g. using a dead letter queue) and automatic testing. You can test EVERYTHING very easily using a Camel-extension of JUnit! And again, you always use the same concepts, no matter which technology you have to support. Apache Camel is mature and production ready. It offers scalability, transaction support, concurrency and monitoring. Commercial support is available by FuseSource: http://fusesource.com/products/enterprise-camel When NOT to use Apache Camel? Well, yes, there exist some use cases where I would not use Apache Camel. I have illustrated this in the following graphic (remember the three alternatives I mentioned above: own custom integration, integration framework, enterprise service bus).If you have to integrate just one or two technologies, e.g. reading a file or sending a JMS message, it is probably much easier and faster to use some well known libraries such as Apache Commons IO or Spring JmsTemplate. But please do always use these helper classes, pure File or JMS integration with try-catch-error is soooo ugly! Although FuseSource offers commercial support, I would not use Apache Camel for very large integration projects. An ESB is the right tool for this job in most cases. It offers many additional features such as BPM or BAM. Of course, you could also use several single frameworks or products and „create“ your own ESB, but this is a waste of time and money (in my opinion). Several production-ready ESBs are already available. Usually, open source solutions are more lightweight than commercial products such as WebSphere Message Broker (you probably need a day or two just to install the evaluation version of this product)! Well-known open source ESBs are Apache ServiceMix, Mule ESB and WSO2 ESB. By the way: Did you know that some ESB base on the Apache Camel framework (e.g. Apache Service Mix and the Talend ESB). Thus, if you like Apache Camel, you could also use Apache ServiceMix or the commercial Fuse ESB which is based on ServiceMix. Conclusion Apache Camel is an awesome framework to integrate applications with different technologies. The best thing is that you always use the same concepts. Besides, support for many many technologies, good error handling and easy automatic testing make it ready for integration projects. Because the number of applications and technologies in each company will increase further, Apache Camel has a great future. Today we have application silos, in ten years we will probably have cloud silos which are deployed in Goggle App Engine, CloudFoundry, Amazon EC3, or any other cloud service. So I hope that Apache Camel will not oversleep to be ready for the cloud era, too (e.g. by offering components to connect to cloud frameworks easily). But that’s future… At the moment you really should try this framework out, if you have to integrate applications in the JVM / Java environment. By the way: I know that I praise Camel in this article, but I am neither a Camel committer nor working for FuseSource. I just really like this framework. Best regards, Reference: When to use Apache Camel? from our JCG partner Kai Wahner at the Blog about Java EE / SOA / Cloud Computing blog....
devops-logo

It’s About Confidentiality and Integrity (not so much Availability)

Everyone knows the C-I-A triad for information security: security is about protecting the Confidentiality, Integrity and Availability of systems and data. In a recent post, Warren Axelrod argues that Availability is the most important of these factors for security, more important than Integrity and Confidentiality – that C-I-A should be A-I-C. I don’t agree. Protecting the Confidentiality of customer data and sensitive business data and system resources is a critical priority for information security. It’s what you should first think about in security. And protecting the Integrity of data and systems, through firewalls and network engineering and operational hardening, and access control, data validation and encoding, auditing, digital signatures and so on is the other critical priority for information security. Availability is a devops problem, not a security problem Axelrod makes the point that it doesn’t matter if the Confidentiality or Integrity of data is protected if the system isn’t available, which is true. But Availability is already the responsibility of application architects and operations engineers. Their job is designing and building scalable applications that can handle load surges and failures, and architecting and operating technical infrastructure that is equally resilient to load and failures. Availability of systems is one of the key ways that their success is measured and one of the main things that they get paid to take care of. Availability of systems and data is a devops problem that requires application developers and architects and operations engineers to work together. I don’t see where security experts add value in ensuring Availability – with the possible exception of helping architects and engineers understand how to protect themselves from DDOS attacks. When it comes to Availability, I look to people like James Hamilton and Michael Nygard and John Allspaw for guidance and solutions, not to application security experts. In information security, C-I-A should be C and I, with a little bit of A – not the other way around. Reference: It’s About Confidentiality and Integrity (not so much Availability) from our JCG partner Jim Bird at the Building Real Software blog....
java-logo

Plan B? That is Plan N … Nothing. Jigsaw follows in 2015

What a day. When the typical European is winding down people in the States are starting with coffee. This is why I had a good night sleep over the recent news by Mark Reinhold. In a post titled ‘ Project Jigsaw: Late for the train‘ he proposes to ‘defer Project Jigsaw to the next release, Java 9.’ With the modularization efforts being one of the key topics of Java’s future on recent conferences and blog-posts this was a quite surprising move. Yesterday everybody was speculating about if there will be an JSR for Jigsaw or not. Today we know why this didn’t happen. And I am disappointed about that. Here is why. Early notification? No – it’s salami slicing! Or? My first impression was: Hey, you guys don’t get it. Dropping features late in the timeline isn’t good for the community. But Donald made me realize that Java 8 is scheduled for May 2013. @ myfear @ jponge @ alexismp Again, I’m truly sorry that an 18 month in advance proposal isn’t good enough for you. — DonaldOJDK (@DonaldOJDK) July 17, 2012 That basically means, we are informed 18 months ahead. But you guessed right. The reason for me being disappointed isn’t the time. It’s about the way the future of Java has been communicated and used for marketing. Bert Ertmann naild it for me with his tweet:Plan B was promised for fall ’12. Then became fall ’13 and now one of its key features becomes fall ’15. Boy, what a mess! #jigsaw — Bert Ertman (@BertErtman) July 17, 2012 It seems to be a pattern here. Slicing everything until nothing relevant remains. But wait. Haven’t we all seen the save harbor slides? Have we been ignoring them? Or aren’t we aware of their real importance? Could all this be an agile planning process which simply isn’t communicated in the right way? The community as the most important stakeholder (beside Oracle internal interests) obviously wasn’t aware of the true reliability of the statements and plans. I have seen that before. And struggled with the same approach. Outlining the planning a bit more or even adding a burn down chart for the progress would be a very helpful instrument for a sneak into what’s actually happening with the development. No, I’m not proposing to see all the little numbers, but I would love to have an indicator about stuff that is working like it was planned and stuff that is … being postponed. I don’t want to miss the chance to say thanks to Donald and Mark and also Dalibor and the many others from the OpenJDK/Oracle team for listening to the community. I am thankful to see them on Twitter, Email, Blogs, Forums and everywhere around to gather feedback and try to work on the way Oracle is communicating proposals and decisions. The real reasons? Are there any more reasons behind that than the ones Mark expressed in his blog? ‘some significant technical challenges remain’ and there is ‘not enough time left for the broad evaluation, review, and feedback which such a profound change to the Platform demands.’ Following Mark’s twitter stream also reveals some more insights here. ‘Started on a shoestring at Sun, barely survived integration into Oracle, only fully staffed about a year ago …’ ( @mreinhold) For the external person the news sounded like … wow that stuff has been started years ago and nobody was actually coding there? With the insights from Mark about I hope he is doing another blog-post about this does actually sound a little different. It might be that the truth is much simpler here. And it also would be good to know what the community can do to help. Mark: Go on! Keep lifting the former secret parts and try to facilitate what the community has to offer! Dreams of Java on iOS over?Do you remember what has been said at last JavaOne? The iOS and Android versions of JavaFX? Mobile goddess is back with Java since Java ME never really lifted up? Awesome. One of the most prominent requirements for that to happen was the ability to repackage the JDK to the right size for the job. Jigsaw was the idea behind that. As of today Mark proposes to introduce ‘one or more compact Profiles in the Java SE 8 spech http://mail.openjdk.java.net/pipermail/java-se-8-spec-observers/2012-July/000001.html to solve the missing module system. This in fact wouldn’t be a ‘module’ system but simply ‘just different ways to build the JDK, resulting in different-sized JREs.’ ( @mreinhold). Yeah. Ok. And asked for the implications that might have the answer was: ‘We’ve already been preparing for the complexity of building and testing a modular platform.’ ( @mreinhold) Seems as if the building blocks of that proposal are in place and no additional overhead is needed to get the mobile promises on the road. So we will not have to fear >100 MB downloads for the JavaFX based apps. I don’t know if they will meet the proposed distribution size starting at 10 MB. But anyway I expect it to be at a reasonable size. We don’t need Jigsaw!? Really? We already have OSGI, JBoss Modules, HK2 Kernel abstraction. A lot of stuff is in place and Jigsaw would only have helped the JDK. Really? I’m looking at it from a slightly different perspective. Even if it is true that a module system would have helped the JDK in the first place, the dependent platform specifications (like Java EE) also are in big need for a module system. And Java simply hasn’t anything to over here. At least nothing that is in the reach of the JCP. So, looking for modularization approaches as of today would mean to embrace non JCP technologies. And we all know that this will not happen. So, looking at Java EE 7 and beyond we are quite sure that this proposal is putting a lot of pressure on the internal discussions. Not to forget about the additional years the competitors gain in entering and deciding the field. If you ask me, the worst thing that could happen is that Jigsaw ends up with being used JDK internally only. There is a good chance for exactly that to happen. What is left of Java 8? With Jigsaw being stripped of the Java 8 time-frame the most important question here is about the what is left. Even still under the save harbor statements that’s basically: - Project Lambda (JSR 335) will bring closures to the Java programming language. - New Date/Time API (JSR 310) - Type Annotations (JSR 308) - A couple of smaller feature With the new scope Java 8 will ship on time, around September 2013 according to Mark. Feeling better now? I don’t know. Even a good night sleep didn’t bring back that comfy feeling I had a few days ago talking about modularization with Java. But I think I have to get over it and this is still another one of those ‘bad-hair’ days which don’t have a real reason for feeling sad. Seems as if I personally have to look at the alternatives. Waiting until 2015 is not an option. OSGI, JBoss Modules … Here I come. Update 20.07.12 Alexis has put up an interesting piece about motivation and the true debacle behind Jigsaw: “As I wrote above, Oracle has the resources to declare Jigsaw a strategic goal. I can agree that it may be hard to deliver by late 2013 but waiting for 2016 is effectively killing Jigsaw and encouraging everyone to look at alternatives which will jeopardize yet even more Jigsaw’s chances of ever seeing the light of day. In fact, even Oracle is considering profiles in Java 8, an ugly band-aid if you ask me. One you’ll need to painfully tear off to get proper modularity in the platform. Jigsaw really shouldn’t be seen as “a new feature”, to me it’s really the Java reboot some people have been calling for a long time. Only a compatible one.” Reference: Plan B? That is Plan N … Nothing. Jigsaw follows in 2015 from our JCG partner Markus Eisele at the Enterprise Software Development with Java blog....
Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close