Featured FREE Whitepapers

What's New Here?


Android – Load WebView with ProgressBar

Problem: How to load WebView with ProgressBar? Description: Previously, i have published an article for Android – WebViewClient example where we have discussed about how to load URL inside the application instead of opening a native browser. Now, just consider the case where we want to include progress bar to show loading process. At the same time we can either show ProgressDialog or include ProgressBar inside the XML layout. – If we include ProgressBar then we have to make it INVISIBLE or GONE whenever page loading is finished – And if we display ProgressDialog then we have to dismiss it whenever page loading is finished. So in this tutorial, we are going to display ProgressBar. Just check the snap-2 where ProgressBar is invisible as we have made it invisible. Output:Note: Before implementing this solution, make sure you have added INTERNET permission in your AndroidManifest.xml file. <uses-permission android:name="android.permission.INTERNET"> </uses-permission>Solution: WebViewClientDemoActivity.java package com.paresh.webviewclientdemo;import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ProgressBar;/* * Demo of creating an application to open any URL inside the application and clicking on any link from that URl should not open Native browser but that URL should open in the same screen.- Load WebView with progress bar */ public class WebViewClientDemoActivity extends Activity { /** Called when the activity is first created. */WebView web; ProgressBar progressBar;@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);web = (WebView) findViewById(R.id.webview01); progressBar = (ProgressBar) findViewById(R.id.progressBar1);web.setWebViewClient(new myWebClient()); web.getSettings().setJavaScriptEnabled(true); web.loadUrl("http://www.technotalkative.com"); }public class myWebClient extends WebViewClient { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { // TODO Auto-generated method stub super.onPageStarted(view, url, favicon); }@Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // TODO Auto-generated method stubview.loadUrl(url); return true;}@Override public void onPageFinished(WebView view, String url) { // TODO Auto-generated method stub super.onPageFinished(view, url);progressBar.setVisibility(View.GONE); } }// To handle "Back" key press event for WebView to go back to previous screen. @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && web.canGoBack()) { web.goBack(); return true; } return super.onKeyDown(keyCode, event); } }main.xml <!--?xml version="1.0" encoding="utf-8"?--> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"><textview android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="This is the demo of WebView Client" android:textsize="20sp" android:gravity="center_horizontal"> </textview><progressbar android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_gravity="center" android:id="@+id/progressBar1"><webview android:id="@+id/webview01" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_weight="1"> </webview> </progressbar></linearlayout>Download Full source code from here: Android – Load WebView with ProgressBar. Feedback and reviews are always welcome. Please Reference: Android – Load WebView with ProgressBar from our JCG partner Paresh N. Mayani at the TechnoTalkative blog....

Isn’t Java a Civilised Language?

A few weeks ago I was given the opportunity to learn iOS programming. My boss decided that I was more of a ‘computer scientist’ rather than a developer, and this meant that I could apply my knowledge to developing an iPad application or two – all I’d need to do was to learn Objective-C and the iOS SDK: after all, how hard can it be? Although I’ve done lots of C/C++ in the past, I’ve been doing Java since 2001, so I’d virtually forgotten much of what I knew, and besides, Objective-C isn’t much like C++ anyway. The result is that you feel like you’ve washed up on a foreign shore unable to speak the language and you’re armed with nothing more than a sun tan and a dictionary. In learning all this new stuff, I came to realise that Java is a VERY good language and the reason is, firstly and foremost, because you don’t have to think about memory allocation and deallocation, you can just get on with writing your application. In writing iOS applications in Objective-C, you have to both allocate memory for your objects and then clear up after yourself, returning your object’s memory back to the free-pool. This seems very old school for the second decade of the 21st century. Furthermore, having allocated memory for an object, you have to keep track of the number of references there are to it – a practice known as reference counting, something I first came across in my previous life as a C++ programmer. The fundamental idea here is that every time you create a new reference to an object, you increment the reference counter and when you’ve finished with the object reference you decrement its reference counter. When the counter reaches zero, the the system releases the memory back to the free pool. In Objective-C, the function to decrement the reference count is called release; hence if Java had reference counting and if I wanted to, for example, ask an AddressService to find me an address, I’d need to do something like this: // create an object and set the reference count to 1 AddressService addressService = new AddressService(); // Use the object Address address = addressService.findAddress(id); // pass it to a method model.addAttribute("address", address); // free the memory addressService.release();That’s the simple scenario, but what happens if some method or other passes you an object reference as a method argument? In that case you have to decide how you’re going to hang on to it and there seem to be two ways of doing this. The first is to make a copy of the object and the second is to increment its reference count. Making a copy is probably the safest idea, but consumes more memory and will be slower, whilst incrementing the reference count is quick but not as safe as some other part of the program may get the reference counting wrong and decrement the count one too many times, which means that you’ve got a reference to some memory that may have been released, and when you try to access your released object your program will crash…. Again, if Java had reference counting then a Spring Controller request handler method would look something like this: @RequestMapping(value = "/find", method = RequestMethod.GET) public String findAddress(@RequestParam("id") int id, Model model) { // increment the reference count - 'retain' is the Objective-C method for doing this. model.retain();// create a new string object - with reference count of one String msg = new String().withFormat("Processing an address page request for address with id: " + id); // pass the string to the logger logger.info(msg); // release the string's memory msg.release();AddressService addressService = new AddressService(); Address address = addressService.findAddress(id); model.addAttribute("address", address); addressService.release();// finished with the model model.release(); return "address-display"; }There are a couple of points to note here – firstly, the handler method is passed a model object, so I increment the reference count by calling retain and then call release on the model when I’m finished with it at the end of the method. Secondly, even when creating trivial objects, like a message string that’s passed to a logger, you have to apply the reference counting rules and free the memory once you’ve finished with it. The example below demonstrates the alternative to incrementing the reference count: making your own copy of an object… @RequestMapping(value = "/find", method = RequestMethod.GET) public String findAddress(@RequestParam("id") int id, Model model) { // increment the reference count - 'retain' is the Objective-C method for doing this. Model myModel = model.copy();// As previous example // finished with the model myModel.release(); return "address-display"; }These examples are only trivial, there’s a whole bunch of reference counting rules that you need to apply and if you get it wrong then Ka-Bam your program crashes and getting it wrong means either you try to access memory that’s already been freed, or slowly die due to a memory leak because you’ve forgotten to release some memory. Although I guess that the key point here is ownership: if you own an object, increment it’s reference count, when you’re finished with an object then decrement its reference count. The code above is just a bit of scribble written to illustrate the point – it won’t compile. The code was actually taken from my Address sample on GitHub and in real life looks like this: @RequestMapping(value = "/find", method = RequestMethod.GET) public String findAddress(@RequestParam("id") int id, Model model) {logger.info("Processing an address page request for address with id: " + id);Address address = addressService.findAddress(id); model.addAttribute("address", address);return "address-display"; }…much smaller neater and more understandable. One last point, some of you will have noticed that in the reference counting example, I allocate (Objective-C word) a new AddressService - this is because iOS programming has nothing like dependency injection or a Spring framework, so you’re back to creating objects for yourself. (Note to the Guys at Spring: ‘Spring iOS’ – sounds like an idea to me…) Those of you in the know will highlight the fact that Apple recently introduced something called ‘Automatic Reference Counting’. Whilst it isn’t garbage collection, it’s simplifies things in that iOS will now automatically keep track of your pointer references and free memory for you when the count reaches zero, which means that you don’t have to bother calling the retain and release methods. Also, this blog isn’t trying to denigrate Objective-C – I quite like Objective-C. Its syntax seems rather arcane and feels verbose when compared to Java, but it forces you to be more disciplined in your programming technique, so if like me you believe that good programming is down to ‘clarity of thought’, then when writing an Objective-C program you have to think a little bit more clearly, and that I really like. I also guess that a lot of readers might come up with a whole bunch of reasons as to why they think Java is a terrible language, and why their preferred language ‘does it better’, whatever it might be, so I’m looking forward to your comments… Finally, I’m just a ‘newbie’ when it comes to iOS programming, so if any iOS/Objective-C masters come across this blog – please let me know where I’m wrong. Reference: Isn’t Java a Civilised Language? from our JCG partner Roger Hughes at the Captain Debug’s Blog ....

Spring MVC and JQuery for Ajax Form Validation

In this tutorial, we will see how to validate a form on server side using Ajax with Spring MVC and JQuery. Spring MVC provides a very convenient process for adoption of Ajax with annotation driven configuration. We will use this annotation driven configuration to send Ajax response in form of JSON data. The response will contain state of the form validation and error messages in any error exist in form data.Tools Used:Spring MVC 3.0.3 JQuery 1.4.2 Jackson 1.5.3In the example, we will add users with name and education to a list using Ajax and Spring MVC. The user data will be send to Spring MVC controller with the help of JQuery and the controller will return the full list of users added till time if there is no validation error in form data or the controller will return validation errors if they present in form data. So, we will learn two important things in this tutorial:How to validate form data using Ajax in Spring MVC with the help of JQuery? and how send back list of objects to Ajax call as response ?Domain Class for User Following is our User domain class that will hold the form data:package com.raistudies.domain;public class User {private String name = null; private String education = null;public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEducation() { return education; } public void setEducation(String education) { this.education = education; } }There are two fields in our User domain object name and education. Ajax response domain class for sending JSON response Following is the domain object that will we use to send response: package com.raistudies.domain;public class JsonResponse { private String status = null; private Object result = null; public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public Object getResult() { return result; } public void setResult(Object result) { this.result = result; }}It contain two properties, “status” and “result”. “status” field is of type String and will contain “FAIL” or “SUCCESS”. “result” will contain the other data that are to be send back to the browser. UserController.java package com.raistudies.controllers;import java.util.ArrayList; import java.util.List;import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.validation.BindingResult; import org.springframework.validation.ValidationUtils; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody;import com.raistudies.domain.JsonResponse; import com.raistudies.domain.User;@Controller public class UserController { private List<User> userList = new ArrayList<User>();@RequestMapping(value="/AddUser.htm",method=RequestMethod.GET) public String showForm(){ return "AddUser"; }@RequestMapping(value="/AddUser.htm",method=RequestMethod.POST) public @ResponseBody JsonResponse addUser(@ModelAttribute(value="user") User user, BindingResult result ){ JsonResponse res = new JsonResponse(); ValidationUtils.rejectIfEmpty(result, "name", "Name can not be empty."); ValidationUtils.rejectIfEmpty(result, "education", "Educatioan not be empty"); if(!result.hasErrors()){ userList.add(user); res.setStatus("SUCCESS"); res.setResult(userList); }else{ res.setStatus("FAIL"); res.setResult(result.getAllErrors()); }return res; }}showForm() is used to shoe the Add user form to browser. method addUser() is will handle the ajax request and validate the User object and if there is no validation error in form data it will set the userList object to result property of JsonResponse class with status as “SUCCESS“. But, if there are errors in form data it will extract list of errors from BindingResult object using getAllErrors() method and set to result property of JsonResponse class with status as “FAIL“. AddUser.jsp Following is the jsp page that calls the UserController using Ajax with the help of JQuery:<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Add Users using ajax</title> <script src="<%=request.getContextPath() %>/js/jquery.js"></script> <script type="text/javascript"> var contexPath = "<%=request.getContextPath() %>"; </script> <script src="<%=request.getContextPath() %>/js/user.js"></script> <link rel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/style/app.css"> </head> <body> <h1>Add Users using Ajax ........</h1> <table> <tr><td colspan="2"><div id="error" class="error"></div></td></tr> <tr><td>Enter your name : </td><td> <input type="text" id="name"><br/></td></tr> <tr><td>Education : </td><td> <input type="text" id="education"><br/></td></tr> <tr><td colspan="2"><input type="button" value="Add Users" onclick="doAjaxPost()"><br/></td></tr> <tr><td colspan="2"><div id="info" class="success"></div></td></tr> </table> </body> </html>The jsp page includes a js file user.js that has been used for holding the definition of the JavaScript method doAjaxPost() which produces the ajax class and also use the response of the Ajax call to dynamically update the page data. user.js Following is the code for ajax class and interpreting the response received from Spring MVC controller: function doAjaxPost() { // get the form values var name = $('#name').val(); var education = $('#education').val();$.ajax({ type: "POST", url: contexPath + "/AddUser.htm", data: "name=" + name + "&education=" + education, success: function(response){ // we have the response if(response.status == "SUCCESS"){ userInfo = "<ol>"; for(i =0 ; i < response.result.length ; i++){ userInfo += "<br><li><b>Name</b> : " + response.result[i].name + ";<b> Education</b> : " + response.result[i].education; } userInfo += "</ol>"; $('#info').html("User has been added to the list successfully. " + userInfo); $('#name').val(''); $('#education').val(''); $('#error').hide('slow'); $('#info').show('slow'); }else{ errorInfo = ""; for(i =0 ; i < response.result.length ; i++){ errorInfo += "<br>" + (i + 1) +". " + response.result[i].code; } $('#error').html("Please correct following errors: " + errorInfo); $('#info').hide('slow'); $('#error').show('slow'); } }, error: function(e){ alert('Error: ' + e); } }); }$.ajax() method of JQuery has been used for making an Ajax call here which sends the form data name and education field values to Spring Controller. On success of the Ajax call, it first checks the status field of the response. Note that, the response object here is the JSON representation of the JsonResponse java object. If the status field of the response is “SUCCESS” then it iterates through the user list using the notation response.result[i] , note that the list object of java is converted to json array by Jackson library. If the status is “FAIL” the the result object will contain the validation errors which we can access using the notation response.result[i].code , here the code will return error message added in Spring controller. While running the example in tomcat 6 server, it will open following form :Ajax Validation FormJust click on the “Add Users” button without entering any value, it will show errors for the field as shown in the bellow image:Ajax Validation Show Error in PageNow enter any name and education and click on the “Add Users” button. It will add the user detail to list and also show the info of the whole user list on the page :Ajax Validation with Spring MVC and JQuery Success PageYou can also try the example by downloading the example from bellow links: Source: Download Source + Lib :Download Reference: Ajax Form Validation using Spring MVC and JQuery from our JCG partner Rahul Mondal at the Rai Studies blog....

Spring and Quartz: Multi-Job Scheduling Service

Job Scheduling is so important requirement for the applications. Especially in large-scale projects, working with a lot of jobs can be a problem. Spring and Quartz have brought significant benefits for the solution of this problem. This article shows how to schedule multi jobs easily by using Spring and Quartz. Used Technologies : JDK 1.6.0_21 Spring 3.1.1 Quartz 1.8.5 Maven 3.0.2 STEP 1 : CREATE MAVEN PROJECT A maven project is created as below. (It can be created by using Maven or IDE Plug-in)STEP 2 : LIBRARIES Spring dependencies are added to Maven’ s pom.xml. <!-- Spring 3 dependencies --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency>STEP 3 : CREATE TASK CLASSES A FirstTask Class is created. package com.otv.task; import org.apache.log4j.Logger; /** * First Task * * @author onlinetechvision.com * @since 24 Feb 2012 * @version 1.0.0 * */ public class FirstTask { private static Logger log = Logger.getLogger(FirstTask.class); /** * Execute this task * */ public void execute() { log.debug("FirstTask runs successfully..."); } }A SecondTask Class is created. package com.otv.task; import org.apache.log4j.Logger; /** * Second Task * * @author onlinetechvision.com * @since 24 Feb 2012 * @version 1.0.0 * */ public class SecondTask { private static Logger log = Logger.getLogger(SecondTask.class); /** * Execute this task * */ public void execute() { log.debug("SecondTask runs successfully..."); } }STEP 4 : CREATE ISchedulerService INTERFACE ISchedulerService Interface is created. package com.otv.service; /** * Scheduler Service Interface * * @author onlinetechvision.com * @since 24 Feb 2012 * @version 1.0.0 * */ public interface ISchedulerService { /** * Execute First Task * * @param * @throws * @return */ public void executeFirstTask(); /** * Execute Second Task * * @param * @throws * @return */ public void executeSecondTask(); }STEP 5 : CREATE SchedulerService CLASS SchedulerService Class is created by implementing ISchedulerService Interface. This service schedules tasks. package com.otv.service; import com.otv.task.FirstTask; import com.otv.task.SecondTask; /** * Scheduler Service Implementation * * @author onlinetechvision.com * @since 24 Feb 2012 * @version 1.0.0 * */ public class SchedulerService implements ISchedulerService { private FirstTask firstTask; private SecondTask secondTask; /** * Execute First Task * */ public void executeFirstTask() { getFirstTask().execute(); } /** * Execute Second Task * */ public void executeSecondTask() { getSecondTask().execute(); } /** * Get First Task * * @return FirstTask */ public FirstTask getFirstTask() { return firstTask; } /** * Set First Task * * @param firstTask First Task */ public void setFirstTask(FirstTask firstTask) { this.firstTask = firstTask; } /** * Get Second Task * * @return SecondTask */ public SecondTask getSecondTask() { return secondTask; } /** * Set Second Task * * @param secondTask Second Task */ public void setSecondTask(SecondTask secondTask) { this.secondTask = secondTask; } }STEP 6 : CREATE Application CLASS Application Class is created. This class runs the application. package com.otv.starter; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Application Starter Class * * @author onlinetechvision.com * @since 24 Feb 2012 * @version 1.0.0 * */ public class Application { /** * Main method of the Application * */ public static void main(String[] args) { new ClassPathXmlApplicationContext("applicationContext.xml"); } }STEP 7 : DEFINE Job Detail CONFIGURATIONS Job Details can be defined via two ways in Spring. By using MethodInvokingJobDetailFactoryBean or by extending QuartzJobBean. In this example, MethodInvokingJobDetailFactoryBean method has been used. targetObject and targetMethod properties are given to MethodInvokingJobDetailFactoryBean. <!-- Job Details--> <bean id="FirstTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="SchedulerService" /> <property name="targetMethod" value="executeFirstTask" /> </bean> <bean id="SecondTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="SchedulerService" /> <property name="targetMethod" value="executeSecondTask" /> </bean>STEP 8 : DEFINE Trigger CONFIGURATIONS Triggers can also be defined via two ways in Spring. By defining SimpleTriggerBean or CronTriggerBean . When SimpleTriggerBean is used, jobDetail, repeatInterval and startDelay properties are defined. When CronTriggerBean is used, jobDetail and cronExpression properties are defined. In this example, repeat interval of first task has been set 5 secs and repeat interval of second task has been set 12 secs . <!-- Simple Trigger --> <bean id="FirstSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">     <property name="jobDetail" ref="FirstTaskJobDetail" />     <property name="repeatInterval" value="5000" />     <property name="startDelay" value="1000" /> </bean>   <!-- <bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">         <property name="jobDetail" ref="SecondTaskJobDetail" />         <property name="repeatInterval" value="12000" />         <property name="startDelay" value="1000" />     </bean> -->      <!-- Cron Trigger --> <bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">     <property name="jobDetail" ref="SecondTaskJobDetail" />     <property name="cronExpression" value="0/12 * * * * ?" /> </bean>STEP 9 : DEFINE SchedulerFactoryBean CONFIGURATION Finally, Job Details and Triggers are configured by creating SchedulerFactoryBean. <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="jobDetails"> <list> <ref bean="FirstTaskJobDetail" /> <ref bean="SecondTaskJobDetail" /> </list> </property> <property name="triggers"> <list> <ref bean="FirstSimpleTrigger" /> <ref bean="SecondSimpleTrigger" /> </list> </property> </bean>STEP 10 : CREATE applicationContext.xml All applicationContext.xml content is shown as below. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- Beans Declaration --> <bean id="FirstTask" class="com.otv.task.FirstTask"></bean> <bean id="SecondTask" class="com.otv.task.SecondTask"></bean> <bean id="SchedulerService" class="com.otv.service.SchedulerService"> <property name="firstTask" ref="FirstTask" /> <property name="secondTask" ref="SecondTask" /> </bean> <!-- Job Details--> <bean id="FirstTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="SchedulerService" /> <property name="targetMethod" value="executeFirstTask" /> </bean> <bean id="SecondTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="SchedulerService" /> <property name="targetMethod" value="executeSecondTask" /> </bean> <!-- Simple Trigger --> <bean id="FirstSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="FirstTaskJobDetail" /> <property name="repeatInterval" value="5000" /> <property name="startDelay" value="1000" /> </bean> <!-- <bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="SecondTaskJobDetail" /> <property name="repeatInterval" value="12000" /> <property name="startDelay" value="1000" /> </bean> --> <!-- Cron Trigger --> <bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="SecondTaskJobDetail" /> <property name="cronExpression" value="0/12 * * * * ?" /> </bean> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="jobDetails"> <list> <ref bean="FirstTaskJobDetail" /> <ref bean="SecondTaskJobDetail" /> </list> </property> <property name="triggers"> <list> <ref bean="FirstSimpleTrigger" /> <ref bean="SecondSimpleTrigger" /> </list> </property> </bean> </beans>STEP 11 : RUN PROJECT After Application Class is started, below output logs will be shown : 25.02.2012 00:17:18 DEBUG (FirstTask.java:23) - FirstTask runs successfully... 25.02.2012 00:17:23 DEBUG (FirstTask.java:23) - FirstTask runs successfully... 25.02.2012 00:17:24 DEBUG (SecondTask.java:22) - SecondTask runs successfully... 25.02.2012 00:17:28 DEBUG (FirstTask.java:23) - FirstTask runs successfully... 25.02.2012 00:17:33 DEBUG (FirstTask.java:23) - FirstTask runs successfully... 25.02.2012 00:17:36 DEBUG (SecondTask.java:22) - SecondTask runs successfully... 25.02.2012 00:17:38 DEBUG (FirstTask.java:23) - FirstTask runs successfully... 25.02.2012 00:17:43 DEBUG (FirstTask.java:23) - FirstTask runs successfully... 25.02.2012 00:17:48 DEBUG (SecondTask.java:22) - SecondTask runs successfully... 25.02.2012 00:17:48 DEBUG (FirstTask.java:23) - FirstTask runs successfully... 25.02.2012 00:17:53 DEBUG (FirstTask.java:23) - FirstTask runs successfully... 25.02.2012 00:17:58 DEBUG (FirstTask.java:23) - FirstTask runs successfully... 25.02.2012 00:18:00 DEBUG (SecondTask.java:22) - SecondTask runs successfully...STEP 12 : DOWNLOAD OTV_SpringQuartz_MultiJobScheduling Reference: Multi-Job Scheduling Service by using Spring and Quartz from our JCG partner Eren Avsarogullari at the Online Technology Vision blog....

Customized Internationalization (i18n) in Java

Internationalization (i18n) is very important in our software projects. It brings mainly these benefits:Externalizing UI strings into external files other than code files and so easy-to-manage UI content. Supporting multiple languages.In this post, a brief practical example of i18n will be given for Eclipse and Java projects, including customizing i18n mechanism to have more maintainable and encapsulated approach.First, we must have some classes which includes string values shown on user interface:An example UI classThen we must have an instance of an i18n utility class. This is generally one of the two in Java:java.util.ResourceBundle (doesn’t need spring dependency)ResourceBundle initializationorg.springframework.context.support.ResourceBundleMessageSource (has multiple word externalization capability (which will be told later)).ResourceBundleMessageSource initializationWe’ll use ResourceBundleMessageSource instance in this tutorial because of its extended capabilities.Then right click on the class and choose Source –> Externalize Strings. A window as below will be shown. Enter keys for strings into the right column. Keys will be started with class name as default. Keys must be unique on the system, so a predefined pattern should be applied (e.g. <class_name>.<type_id>.<description>)Eclipse string externalization windowClick Next–> Finish and your strings will be changed as follows. And also Messages class and externalizer properties file will be created automatically (auto-comments on the right are markers for eclipse which means “externalized”):Class with externalized stringsAuto-created i18n utility and property classesNow externalization is complete. But we want i18n, and we must support multiple languages. For this, define another properties file with location post-tag (e.g. “EN”, “FR”, “TR”, …), copy keys and fill values with new language and set locale of resource bundle in a proper place/action of your application (e.g. on settings window or login page):Multiple property files for each languageMessages_tr_TR.properties file contentSetting new locale to the resource bundleAs the last step, we want to encapsulate i18n utility class and also want to use a more  capable i18n utility (e.g. ResourceBundleMessageSource). For this, define a class as below:Customized and encapsulated message source (i18n utility) classFinally, change “Messages.getString” statements into your new instance:Class with externalized strings (with customized i18n utility class)You can also externalize parameterized strings using your class. Its usage will be as follows:Getting a parameterized string from i18n utilityDefining a parameterized string in property fileReference: Customized Internationalization (i18n) in Java – Step by Step from our JCG partner Cagdas Basaraner at the CodeBuild blog....

Client-side server monitoring with Jolokia and JMX

The choice of Java monitoring tools is tremendous (random selection and order powered by Google): javamelodypsi-probeJVisualVMjconsoleJAMonJava JMX Nagios Plugin N/A Besides, there are various dedicated tools e.g. for ActiveMQ, JBoss, Quartz scheduler, Tomcat/tcServer… So which one should you use as an ultimate monitoring dashboard? Well, none of them provide out-of-the-box features you might require. In some applications you have to constantly monitor the contents and size of a given JMS queue. Others are known to have memory or CPU problems. I have also seen software where system administrators had to constantly run some SQL query and check the results or even parse the logs to make sure some essential background process is running. Possibilities are endless, because it really depends on the software and its use-cases. To make matters worse, your customer doesn’t care about GC activity, number of open JDBC connections and whether this nasty batch process is not hanging. It should just work. In this post we will try to develop easy, cheap, but yet powerful management console. It will be built around the idea of a single binary result – it works or not. If this single health indicator is green, no need to go deeper. But! If it turned red, we can easily drill-down. It is possible because instead of showing hundreds of unrelated metrics we will group them in a tree-like structure. The health status of each node in a tree is as bad as the worst child. This way if anything bad happens with our application, it will bubble-up. We are not forcing system administrator to constantly monitor several metrics. We decide what is important and if even tiniest piece of our software is malfunctioning, it will pop-up. Compare this to a continuous integration server that does not have green/red builds and e-mail notifications. Instead you have to go to the server every other build and manually check whether the code is compiling and all tests were green. The logs and results are there, but why parse them and aggregate manually? This is what we are trying to avoid in our home-grown monitoring solution. As a foundation I have chosen (not for the first time) Jolokia JMX to HTTP bridge. JVM already provides the monitoring infrastructure so why reinvent it? Also thanks to Jolokia the whole dashboard can be implemented in JavaScript on the client side. This has several advantages: server footprint is minimal, also it allows us to rapidly tune metrics by adding them or changing alert thresholds. We’ll start by downloading various JMX metrics onto the client (browser). I have developed some small application for demonstration purposes employing as many technologies as possible – Tomcat, Spring, Hibernate, ActiveMQ, Quartz, etc. I am not using the built-in JavaScript client library for Jolokia as I found it a bit cumbersome. But as you can see it is just a matter of a single AJAX call to fetch great deal of metrics. function request() { var mbeans = [ "java.lang:type=Memory", "java.lang:type=MemoryPool,name=Code Cache", "java.lang:type=MemoryPool,name=PS Eden Space", "java.lang:type=MemoryPool,name=PS Old Gen", "java.lang:type=MemoryPool,name=PS Perm Gen", "java.lang:type=MemoryPool,name=PS Survivor Space", "java.lang:type=OperatingSystem", "java.lang:type=Runtime", "java.lang:type=Threading", 'Catalina:name="http-bio-8080",type=ThreadPool', 'Catalina:type=GlobalRequestProcessor,name="http-bio-8080"', 'Catalina:type=Manager,context=/jmx-dashboard,host=localhost', 'org.hibernate:type=Statistics,application=jmx-dashboard', "net.sf.ehcache:type=CacheStatistics,CacheManager=jmx-dashboard,name=org.hibernate.cache.StandardQueryCache", "net.sf.ehcache:type=CacheStatistics,CacheManager=jmx-dashboard,name=org.hibernate.cache.UpdateTimestampsCache", "quartz:type=QuartzScheduler,name=schedulerFactory,instance=NON_CLUSTERED", 'org.apache.activemq:BrokerName=localhost,Type=Queue,Destination=requests', "com.blogspot.nurkiewicz.spring:name=dataSource,type=ManagedBasicDataSource" ]; return _.map(mbeans, function(mbean) { return { type:'read', mbean: mbean } }); } $.ajax({ url: 'jmx?ignoreErrors=true', type: "POST", dataType: "json", data: JSON.stringify(request()), contentType: "application/json", success: function(response) { displayRawData(response); } });Just to give you an overview what kind of information is accessible on the client side, we will first dump everything and display it on jQuery UI accordion: function displayRawData(fullResponse) { _(fullResponse).each(function (response) { var content = $('<pre/>').append(JSON.stringify(response.value, null, '\t')); var header = $('<h3/>').append($("<a/>", {href:'#'}).append(response.request.mbean)); $('#rawDataPanel'). append(header). append($('<div/>').append(content)); }); $('#rawDataPanel').accordion({autoHeight: false, collapsible: true}); }Remember that this is just for reference and debug purposes, we are not aiming to display endless list of JMX attributes.As you can see it is actually possible to implement complete jconsole port inside a browser with Jolokia and JavaScript… maybe next time (anyone care to help?). Back to our project, let’s pick few essential metrics and display them in a list:The list itself looks very promising. Instead of displaying charts or values I have assigned an icon to each metric (more on that later). But I don’t want to go through the whole list all the time. Why can’t I just have a single indicator that aggregates several metrics? Since we are already using jsTree, the transition is relatively simple:On the first screenshot you see a healthy system. There is really no need to drill down since Overall metric is green. However the situation is worse on the second screenshot. System load is alarmingly high, also the Swap space needs attention, but is less important. As you can see the former metrics bubbles up all the way to the overall, top metric. This way we can easily discover what is working incorrectly in our system. You might be wondering how did we achieved this pretty tree while at the beginning we only had raw JMX data? No magic here, see how am I constructing the tree: function buildTreeModel(jmx) { return new CompositeNode('Overall', [ new CompositeNode('Servlet container', [ new Node( 'Active HTTP sessions', jmx['Catalina:context=/jmx-dashboard,host=localhost,type=Manager'].activeSessions, Node.threshold(200, 300, 500) ), new Node( 'HTTP sessions create rate', jmx['Catalina:context=/jmx-dashboard,host=localhost,type=Manager'].sessionCreateRate, Node.threshold(5, 10, 50) ), new Node( 'Rejected HTTP sessions', jmx['Catalina:context=/jmx-dashboard,host=localhost,type=Manager'].rejectedSessions, Node.threshold(1, 5, 10) ), new Node( 'Busy worker threads count', jmx['Catalina:name="http-bio-8080",type=ThreadPool'].currentThreadsBusy, Node.relativeThreshold(0.85, 0.9, 0.95, jmx['Catalina:name="http-bio-8080",type=ThreadPool'].maxThreads) ) ]), //... new CompositeNode('External systems', [ new CompositeNode('Persistence', [ new Node( 'Active database connections', jmx['com.blogspot.nurkiewicz.spring:name=dataSource,type=ManagedBasicDataSource'].NumActive, Node.relativeThreshold(0.75, 0.85, 0.95, jmx['com.blogspot.nurkiewicz.spring:name=dataSource,type=ManagedBasicDataSource'].MaxActive) ) ]), new CompositeNode('JMS messaging broker', [ new Node( 'Waiting in "requests" queue', jmx['org.apache.activemq:BrokerName=localhost,Destination=requests,Type=Queue'].QueueSize, Node.threshold(2, 5, 10) ), new Node( 'Number of consumers', jmx['org.apache.activemq:BrokerName=localhost,Destination=requests,Type=Queue'].ConsumerCount, Node.threshold(0.2, 0.1, 0) ) ]) ]) ]); }The tree model is quite simple. Root node can have a list of child nodes. Every child node can be either a leaf representing a single evaluated JMX metric or a composite node representing set of grandchildren. Each grandchild can in turns be a leaf or yet another composite node. Yes, it is a simple example of Composite design pattern! However it is not obvious where Strategy pattern was used. Look closer, each leaf node object has three properties: label (what you see on the screen), value (single JMX metric) and an odd function Node.threshold(200, 300, 500)… What is it? It is actually a higher order function (function returning a function) used later to interpret JMX metric. Remember, the raw value is meaningless, it has to be interpreted and translated into good-looking icon indicator. Here is how this implementation works: Node.threshold = function(attention, warning, fatal) { if(attention > warning && warning > fatal) { return function(value) { if(value > attention) { return 1.0; } if(value > warning) { return 0.5; } if(value > fatal) { return 0.0; } else { return -1.0; } } } if(attention < warning && warning < fatal) { return function(value) { if(value < attention) { return 1.0; } if(value < warning) { return 0.5; } if(value < fatal) { return 0.0; } else { return -1.0; } } } throw new Error("All thresholds should either be increasing or decreasing: " + attention + ", " + warning + ", " + fatal); }Now it becomes clear. The function receives level thresholds and returns a function that translates them to number in -1:1 range. I could have returned icons directly but I wanted to abstract tree model from GUI representation. If you now go back to Node.threshold(200, 300, 500) example of Active HTTP sessions metric it is finally obvious: if the number of active HTTP sessions exceed 200, show attention icon instead of OK. If it exceeds 300, warning appears. Above 500 fatal icon will appear. This function is a strategy that understands the input and handles it somehow. Of course these values/functions are only examples, but this is where real hard work manifests – for each JMX metric you have to define a set of sane thresholds. Is 500 HTTP sessions a disaster or only a high load we can deal with? Is 90% CPU load problematic or maybe if it is really low we should start worrying? Once you fine-tune these levels it should no longer be required to monitor everything at the same time. Just look at the top level single metric. If it is green, have a break. If it is not, drill-down in few seconds to find what the real problem is. Simple and effective. And did I mention it does not require any changes on the server side (except adding Jolokia and mapping it to some URL)? Obviously this is just a small proof-of-concept, not a complete monitoring solution. However if you are interested in trying it out and improving, the whole source code is available - as always on my GitHub account. Reference: Client-side server monitoring with Jolokia and JMX from our JCG partner Tomasz Nurkiewicz at the Java and neighbourhood blog....

Maven Archetype Creation Tips

I recently needed to create some Maven Archetypes for the Turmeric SOA project. A Maven Archetype for those that don’t know is a way to generate a project based off some pre-canned project templates. In the case of the current Turmeric SOA archetype, it will create a multi-module maven project, that contains the Interface, and Service projects, along with a basic WSDL, and the POMs configured appropriately. This can be run either at the Command Line or through the New Maven Project wizard of m2eclipse. Other IDE’s such as NetBeans, IntelliJ, and others can use it as well, through their support of Maven Archetypes. The hardest thing with getting started with Maven Archetypes is the relatively poor documentation that exists. Beyond the most basic use (archetype:create-from-project), which creates an archetype given an existing maven project or parent-project, there isn’t much to go on. So here are some tips. Directory/Filename Substitution There are cases during template generation where you want to output different module names and sometimes different filenames. To do this rename the portion of the directory or file you want to have substitued with a variable name. For example, if you specify __rootArtifactId__ as part of a Directory name or Filename, what ever is entered as the artifactId during the mvn archetype:generate will be substituted. You can do the same with custom properties. Example. Built in properties There are some built in properties that can be used during substitution. These are:groupId artifactId rootArtifactId version package – a base java package name, that is placed in src/main/java during project creation.You can use these in your POM and other file templates as well. Archetype-metadata.xml The archetype-metadata.xml stored in the archetype-resources/META-INF/maven folder after the project is created, is where you need to tweak what you want generated and how. For modules, you need to tweak attributes:id – This is the name of the module that will be generated. dir – the template dir name – the artifact Id that will be put in the pom file.For the id and name attributes you can use the standard maven properities specification: ${someproperty}. For the dir, you need to use the special __someproperty__ notation. In most cases this will be __rootArtifactId__. An example from the Turmeric SOA archetype. Required Properties Required Properties is how you prompt for additional information that can be substituted in your templates. Any properties you specify will be prompted for during generation. You can pass them in from the command line as well using the -D option. Required properties are referenced in your templates as properties and are substituted during generation. Be careful of specifying default values, default values are not prompted for during generation. They can still be overridden using the -D option. Archetype Catalogs It is important to have an archetype catalog. If you are using Nexus 1.9.x it will automatically search your repositories and generate an archetype catalog for each repository. It scans for all archetypes and as soon as an archetype is deployed the catalog entry is updated. If you don’t have an archetype catalog already, maven can create one for you from your local repository. Just run mvn archetype:crawl. The output will be put in your .m2 repository. Archetypes are important as they allow others to know about your custom archetype, and provide a way for them to be shared and discovered. Hopefull with these few tips, you can spare yourself some of the headaches that I endured. My next task is to help the Minerva project have a few Archetypes created, so that eclipse projects can get started with Tycho a bit easier. Do you have other tips, or items to watch out for? If so, please feel free to add a comment. Reference: Maven Archetype Creation Tips from our JCG partner David Carver at the Intellectual Cramps blog....

Best Of The Week – 2012 – W08

Hello guys, Time for the “Best Of The Week” links for the week that just passed. Here are some links that drew Java Code Geeks attention: * Java.next: In this presentation, the argument that Java is still the best programming language for the JVM (if simplified idioms are used along with proper tooling) is posed. Also see The Most Powerful JVM Language Available and Hate Java? You’re fighting the wrong battle. * The ultimate guide to passwords: Nice article on passwords and security. It discusses password hashing, rainbow attacks, salted hashes, offline cracking, secure passwords (those complex enough to make cracking it uneconomical) and password vaults. Also check out Introduction to Strong Cryptography for a developer’s perspective on the matter. * Installation: Where Software Remains in the Dark Ages: In this article the author criticizes some bad practices related to software installation, such as irreversible changes in the system, extensive use of environment variables, forced reboots and others. * Tracking User Behavior with Google Analytics SDK for Android: This tutorial show how to use the Google Analytics SDK for Android in order to track Android application events like screen loads and button clicks in order to determine what your application’s users are doing. Also check out Android Game Postmortem – ArkDroid Development and “Android Full Application Tutorial” series. * Should All Web Traffic Be Encrypted?: Jeff Atwood discusses web traffic encryption and argues that over the medium to long term, adopting encrypted web connections as a standard for logged-in users is the healthiest direction for the future of the web. Also see Hints for writing secure code. * The 7 habits of highly effective developers: Nice article on the habits that effective developers should adopt, such as adopting proactivity, thinking win-win, beginning with the end in mind and others. * Hidden evils of Java’s String.split() and replace(): This article explores the performance of String’s methods split and replace. Regular expressions should be considered instead of those. Also check out String performance and Exact String Matching. * Smell my Code. Code smell ? What’s code smell?: Short, but to the point, article on code smell, i.e any symptom in the source code of a program that possibly indicates a deeper problem. Common coding smells include duplicated code, large class, feature envy and others. * Tailoring Spring for Custom Usage: This presentation uncovers some of the hooks available in the Spring framework: life cycles, scopes, beans, resources, XML marshallers, REST, transactions, caching, Spring Integration adapters, and others. * Figure out why is JAVA eating CPU?: Short guide on how to identify which Java thread is consuming the system’s CPU. It uses Java’s debugging tools (e.g. jstack) along with Linux’s built-in tools (e.g. ps, grep). * Getting out of the way – Monitoring: In this article, the author suggests that we should be working to make the monitoring happen automatically without Ops involvement. This means that Ops selects monitoring systems that allow for discovery of new metrics & automatic collection of those metrics without additional incremental work each time. Also see Devops has made Release and Deployment Cool. That’s all for this week. Stay tuned for more, here at Java Code Geeks. Cheers, Ilias Tsagklis...

Java 7: WatchService

Of all the new features in Java 7, one of the more interesting is the WatchService, adding the capability to watch a directory for changes. The WatchService maps directly to the native file event notification mechanism, if available. If a native event notification mechanism is not available, then the default implementation will use polling. As a result, the responsiveness, ordering of events and details available are implementation specific. (NOTE: There is a companion post on using the Guava EventBus to process WatchService events) Watching A Directory The Path interface implements the register method that takes a WatchService object and varargs of type WatchEvent.Kind as arguments. There are 4 events to watch for:ENTRY_CREATE ENTRY_DELETE ENTRY_MODIFY OVERFLOWWhile the first 3 types are self explanatory, OVERFLOW indicates that events may been lost or discarded. A WatchService is created by calling FileSystem.newWatchService(). Watching a directory is accomplished by registering a Path object with the WatchService: import static java.nio.file.StandardWatchEventKinds.*; Path path = Paths.get("/home"); WatchService watchService = FileSystems.getDefault().newWatchService(); WatchKey watchKey = path.register(watchService,ENTRY_CREATE,ENTRY_DELETE,ENTRY_MODIFY);As we can see from the example, the register method returns a WatchKey object. The WatchKey is a token that represents the registration of the Path with the WatchService. The WatchKey As a result of the registration process, the WatchKey is in a ‘ready’ state and is considered valid. A WatchKey remains valid until one of the following occurs:WatchKey.cancel() is called. The directory being watched is no longer available. The WatchService object is closed.Checking For Changes When a change is detected, the WatchKey state is set to ‘signaled’ and it is placed in a queue for processing. Getting WatchKeys off the queue involves calling WatchService.poll() or WatchService.take(). Here is a basic example: private boolean notDone = true; while(notDone){ try{ WatchKey watchKey = watchService.poll(60,TimeUnit.SECONDS); List<WatchEvent.Kind<?>> events = watchKey.pollEvents(); for(WatchEvent event : events){ ...process the events } if(!watchKey.reset()){ ...handle situation no longer valid } }catch(InterruptedException e){ Thread.currentThread().interrupt(); }On line 5 we are calling the pollEvents method to retrieve all the events for this WatchKey object. On line 9 you’ll notice a call to the reset method. The reset method sets the WatchKey state back to ‘ready’ and returns a boolean indicating if the WatchKey is still valid. If there are any pending events, then the WatchKey will be immediately re-queued, otherwise it will remain in the ready state until new events are detected. Calling reset on a WatchKey that has been cancelled or is in the ready state will have no effect. If a WatchKey is canceled while it is queued, it will reamin in the queue until retrieved. Cancellation could also happen automatically if the directory was deleted or is no longer available. Processing Events Now that we have detected an event, how do we determine:On which directory did the event happen? (assuming more than one directory registered) What was the actual event? (assuming listening for more than one event) What was the target of the event, i.e what Path object was created,deleted or updated?Jumping in to line 6 in the previous example, we will parse the needed information from a WatchKey and a WatchEvent: //WatchKey watchable returns the calling Path object of Path.register Path watchedPath = (Path) watchKey.watchable(); //returns the event type StandardWatchEventKinds eventKind = event.kind(); //returns the context of the event Path target = (Path)event.context();On line 6 we see the WatchEvent.context method being invoked. The context method will return a Path object if the event was a creation, delete or update and will be relative to the watched directory. It’s important to know that when a event is received there is no guarantee that the program(s) performing the operation have completed, so some level of coordination may be required. Conclusion The WatchService is a very interesting feature of the new java.nio.file package in Java 7. That being said, there are two things that about the WatchService to keep in mind:The WatchService does not pick up events for sub-directories of a watched directory. We still need to poll the WatchService for events, rather than receive asynchronous notification.To address the above issues, there is a follow up post using the Guava EventBus to process the WatchService events. Thanks for your time and see you in the next post.Resourcesjava.nio.file package that contains the WatchService, WatchKey and WatchEvent objects discussed here. A unit test demonstrating the WatchServiceReference: What’s New in Java 7: WatchService from our JCG partner Bill Bejeck at the Random Thoughts On Coding blog....

Is Java’s String Class a God Object?

In October I wrote a blog entitled Top Trumps in God Objects where I talked about the discovery of an object I’d found with 167 disparate methods that linked this object with all other parts of the application and, as you’d expect, followed the general criteria for a God or Monster Object. It was recently pointed out to me that method count alone isn’t an indication that an object is a God Object, which is quite true. The comment also went on to site the String class as an object that isn’t a God Object, but has a large number of methods. This got me thinking: is the String class a well designed class in terms of the general rules of Object Oriented Design? Does it, in fact, break the single responsibility principle or the laws of demeter and is it tightly coupled to all other parts of an application? Is it a God Object? The easy way to answer this is to look at a String in terms of the Single Responsibility Principle, and the best way to do that is to count the number of method calls it has and figure out what they do. If you do that you’ll find that Java’s String class has 66 method calls in it’s repertoire and you may conclude that a number this high could be the first sign of a God Object. Next, if you look at these 66 method calls you can group them into several different areas of responsibility. For example there are: Conversion MethodsgetBytes(...) getChars(...) valueOf(...) toUpperCase(...) toLowerCase(...) toCharArray(...)Methods that split Stringsubstring(...) split(...) subSequence(...)Equivalency Methodsequals(...) matches(...) compareTo(...)Search MethodsindexOf(..) lastIndexOf(...) charAt(...) contains(...)Combining Methodsappend(...) concat(..) + +=…and more besides. Using the lists above, you could now write a CRC card for a String that goes something like this: “A String is responsible for combining itself with other Strings to create new Strings AND converting itself into other objects or arrays of objects AND splitting itself into different pieces AND comparing itself to other String objects AND performing searches on itself” Sticking to the letter of the law then the lists above show that String’s method calls break down into at least five areas of responsibility, which means that, by the book, the Single Responsibility Principle has been violated. Taking this to its logical conclusion, then you could refactor a String to look something like this….However, and this is the question, why isn’t Java’s String class composed of some data and a bunch of classes that operate on it? The answer is both a matter of opinion and multifaceted. Firstly, history… Java as grown over time as so has the String class; methods have been added piece-meal as the Java version number ticks ever upwards. Secondly, pragmatism. A String object in it’s current design may break the Single Responsibility Rule, but it doesn’t matter, it’s easier to leave it as it is and get on with writing the programs that count. Lastly, and I think that this is important, we all generally know what a String is. Its name and meaning is in common usage. If we had to define what a String’s responsible for using a CRC card, then we’d write something like: “a String is responsible for being s String”. A String may have 66 methods, but I believe that by general consensus it’s not a God Object. However, software is just a matter of opinions, so I’ll leave you answer the other questions I posed at the beginning of this blog and to make your own mind up… Reference: Is Java’s String Class a God Object? from our JCG partner Roger Hughes at the Captain Debug’s 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: