tag:blogger.com,1999:blog-89611783366353124292024-03-13T02:39:11.008-07:00Random Eclipse TipsKSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.comBlogger27125tag:blogger.com,1999:blog-8961178336635312429.post-88085795163208206412010-11-18T17:02:00.000-08:002010-11-19T14:13:03.217-08:00Spring Roo, Starting with GWT 2.1 ProjectSpring Roo generates GWT 2.1 project with all the new GWT design features such as Activities, RequestFactory, UIBinder, PlaceController ( If you want to know more about these, watch Google I/O 2010 Ray Ryan's session in here <a href="http://www.google.com/events/io/2010/sessions/architecting-production-gwt.html">http://www.google.com/events/io/2010/sessions/architecting-production-gwt.html</a> . It also generates the Server side persistence logic using AspectJ.<br /><br />In this article we will take a deep look into what are the files Roo generates as there is not enough documentation for a beginner.<br /><br />First download SpringSource Tool Suite from <a href="http://www.springsource.org/roo/start">http://www.springsource.org/roo/start</a>. ( You can also try with Spring Roo Command line and Normal Eclipse Installation ). But lets stick to STS as it provides integration with all spring libraries and Maven build tool.<br /><br />Once you download the installer/Archive for the STS, install it. ( I downloaded the installer exe as it was lot smaller than the archive file ). Installing the STS using the exe file should be straight forward. Just make sure you install all the default packages.<br /><br />Lets start the STS.exe from the installed location. ( Just incase if you have to search for it, It should be inside sts-2.x.x-RELEASE folder inside the installed folder ). Launching the STS.exe would take a while to load ( It's a huge application with lot of eclipe plugins to be loaded). Once it launches, you will see the welcome page like below.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirrVw8dwmREuQTTTnm2c9EMIAdbrN6yAixNmQM8vt72bIlK73s_MYnkRPOQv73X5DZwaHg3LoxhEa4GmDgbeDkG7HsUoHEtB60h-sFdUmX5k71O7-paQ7-MiSIbXJRITNLaW3KK6ZTfqL4/s1600/STS_WelcomePage.jpg"><img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 249px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirrVw8dwmREuQTTTnm2c9EMIAdbrN6yAixNmQM8vt72bIlK73s_MYnkRPOQv73X5DZwaHg3LoxhEa4GmDgbeDkG7HsUoHEtB60h-sFdUmX5k71O7-paQ7-MiSIbXJRITNLaW3KK6ZTfqL4/s320/STS_WelcomePage.jpg" alt="" id="BLOGGER_PHOTO_ID_5541064161631380706" border="0" /></a><br />To install the GWT tools (including the SDK), you simply navigate to the Install Extensions Page. GWT plugin is in Language and Framework tooling sections in the Extensions Tab on the dashboard. The Extensions tab also has few interesting extensions like EclEmma, a code coverage tool, Tasktop Pro, a time tracking tool and so on. But they are optional to follow this article. You will asked to restart the STS after installing the plugins.<br /><br />Now we have SpringSource Tool Suite with Google Web Toolkit with the SDK installed. You will see the google web toolkit actions on the toolbar now as shown in the diagram below.<br /><br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju5rh1OX0qUx1rBA_9yVu8fksTPyH27t2kiqOXsUyf1zSJnfaLNO36jcaouMWMZPCxvxxfyRRu6sVGOL5vhidHmaZDN40De2vLhDGRYzZFQEy7pta6cWKroBz2kQbqbAtq3pz8WgmOQGak/s1600/STS_WelcomePage.jpg"><img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 249px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju5rh1OX0qUx1rBA_9yVu8fksTPyH27t2kiqOXsUyf1zSJnfaLNO36jcaouMWMZPCxvxxfyRRu6sVGOL5vhidHmaZDN40De2vLhDGRYzZFQEy7pta6cWKroBz2kQbqbAtq3pz8WgmOQGak/s320/STS_WelcomePage.jpg" alt="" id="BLOGGER_PHOTO_ID_5541066675445375458" border="0" /></a><br /><br />Lets start with GWT Project creation using Roo shell from Window->Show View -> Roo Shell. ( Since we have installed GWT Plugin, you can also generate the GWT Project using Web Application Project wizard. But that doesnot use Roo's magic of generating all the boiler plate code ).<br /><br />On the Roo Shell View click on "Create New Roo Project" action on the toolbar. Fill in the required information on the roo project creation like Project Name, Top level package name for the GWT Project and click on Finish on the wizard's Next Page. STS creates the Roo project with AspectJ Support, it requires AspectJ weaving support to be enabled. Enable AspectJ weaving and restart the workbench. The Roo_GWT project will be like as shown below.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj92HVD4-h6fcoVZPxF6IMFxEO0TKxG4NwcfdbQCL1TGM2Ym390KQVj1DbUCUN-7eSdtLLWQX_BczJQ3BRetuLvQSAYXWjRwHUt6Z46FE3aEap-RWcsRaYBuLuMhuFGwQ7WTI50oGBQ1nMl/s1600/STS_WelcomePage.jpg"><img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 249px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj92HVD4-h6fcoVZPxF6IMFxEO0TKxG4NwcfdbQCL1TGM2Ym390KQVj1DbUCUN-7eSdtLLWQX_BczJQ3BRetuLvQSAYXWjRwHUt6Z46FE3aEap-RWcsRaYBuLuMhuFGwQ7WTI50oGBQ1nMl/s320/STS_WelcomePage.jpg" alt="" id="BLOGGER_PHOTO_ID_5541069227718415554" border="0" /></a>Click on Open Roo Shell on the Roo Shell view and choose Roo_GWT project. The Roo shell loads the Roo_GWT project and starts the roo.<br /><br />Now to create the GWT project layout on the Roo_GWT project,from the roo prompt type in gwt setup<br /><br /><pre name="code" class="java"><br />Created SRC_MAIN_WEBAPP\WEB-INF\spring<br />Created SRC_MAIN_WEBAPP\WEB-INF\spring\webmvc-config.xml<br />Created SRC_MAIN_WEBAPP\WEB-INF\web.xml<br />Managed SRC_MAIN_WEBAPP\WEB-INF\web.xml<br />gwt setup<br />Managed ROOT\pom.xml [Added dependency org.springframework:spring-web:${spring.version}]<br />Managed ROOT\pom.xml [Added dependency org.springframework:spring-webmvc:${spring.version}]<br />Managed ROOT\pom.xml [Added dependency org.springframework.webflow:spring-js-resources:2.2.0.RELEASE]<br />Managed ROOT\pom.xml [Added dependency commons-digester:commons-digester:2.0]<br />Managed ROOT\pom.xml [Added dependency commons-fileupload:commons-fileupload:1.2.1]<br />Managed ROOT\pom.xml [Added dependency javax.servlet:jstl:1.2]<br />Managed ROOT\pom.xml [Added dependency javax.el:el-api:1.0]<br />Managed ROOT\pom.xml [Added dependency joda-time:joda-time:1.6]<br />Managed ROOT\pom.xml [Added dependency javax.servlet.jsp:jsp-api:2.1]<br />Managed ROOT\pom.xml<br />Managed ROOT\pom.xml [Added dependency com.google.gwt:gwt-servlet:2.1.0]<br />Managed ROOT\pom.xml [Added dependency com.google.gwt:gwt-user:2.1.0]<br />Managed ROOT\pom.xml [Added dependency org.json:json:20090211]<br />Managed ROOT\pom.xml [Added dependency com.googlecode.gwt.inject:gin:1.0]<br />Managed ROOT\pom.xml [Added dependency javax.validation:validation-api:1.0.0.GA]<br />Managed ROOT\pom.xml [Added dependency xalan:xalan:2.7.1]<br />Managed ROOT\pom.xml<br />Managed SRC_MAIN_WEBAPP\WEB-INF\web.xml<br />Managed SRC_MAIN_WEBAPP\WEB-INF\spring\webmvc-config.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client<br />Created SRC_MAIN_JAVA\com\roo\gwt\ApplicationScaffold.gwt.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\request<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ScaffoldDesktopShell.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ScaffoldMobileShell.java.orig<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ScaffoldMobileShell.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ScaffoldDesktopShell.ui.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ScaffoldDesktopApp.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ScaffoldMobileApp.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ScaffoldMobileShell.ui.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ScaffoldApp.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ScaffoldMobileApp.java.orig<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\Scaffold.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\MobileProxyListView.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\ByteParser.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\ByteRenderer.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\CharRenderer.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\FloatRenderer.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\ShortRenderer.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\MobileProxyListView.ui.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\CharBox.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\FloatParser.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\BigDecimalRenderer.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\ShortBox.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\ByteBox.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\ShortParser.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\BigDecimalBox.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\CharParser.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\CollectionRenderer.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\FloatBox.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ui\BigDecimalParser.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui<br />Created SRC_MAIN_JAVA\com\roo\gwt\server<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\MobileListResources.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\mobile.css<br />Created SRC_MAIN_JAVA\com\roo\gwt\shared<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ioc<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ioc\ScaffoldInjector.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ioc\InjectorWrapper.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ioc\ScaffoldModule.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ioc\MobileInjector.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ioc\DesktopInjectorWrapper.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ioc\MobileInjectorWrapper.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\ioc\DesktopInjector.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\ProxyListView.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\ProxyEditView.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\AbstractProxyListActivity.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\AbstractProxyListView.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\ProxyPlace.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\FindAndEditProxy.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\ProxyDetailsView.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\CreateAndEditProxy.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\ScaffoldPlaceHistoryMapper.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\AbstractProxyEditActivity.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\ProxyListPlacePicker.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\ProxyPlaceToListPlace.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\CollectionRenderer.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\PlaceHistoryFactory.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\place\ProxyListPlace.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\images<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\images\createButton.png<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\images\groupIcon.png<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\images\openGradient.png<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\images\selectionGradient.png<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\images\titleGradient.png<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\images\gwtLogo.png<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\images\userIcon.png<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\images\backButton.png<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\style\images\rooLogo.png<br />Created SRC_MAIN_WEBAPP\ApplicationScaffold.html<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\activity<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\activity<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\scaffold\activity\IsScaffoldMobileActivity.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\request\ApplicationEntityTypesProcessor.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\request\ApplicationRequestFactory.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ApplicationListPlaceRenderer.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\activity\ApplicationMasterActivities.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\activity\ApplicationDetailsActivities.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\activity\ScaffoldMobileActivities.java<br /></pre><br /><br />Well, that generated a LOT of classes, files, images in the Roo_GWT project. Lets look at the different types of files it generated.<br /><br /><br /><pre name="code" class="java"><br /><br />Managed ROOT\pom.xml [Added dependency org.springframework:spring-web:${spring.version}]<br />Managed ROOT\pom.xml [Added dependency org.springframework:spring-webmvc:${spring.version}]<br />Managed ROOT\pom.xml [Added dependency org.springframework.webflow:spring-js-resources:2.2.0.RELEASE]<br />Managed ROOT\pom.xml [Added dependency commons-digester:commons-digester:2.0]<br />Managed ROOT\pom.xml [Added dependency commons-fileupload:commons-fileupload:1.2.1]<br />Managed ROOT\pom.xml [Added dependency javax.servlet:jstl:1.2]<br />Managed ROOT\pom.xml [Added dependency javax.el:el-api:1.0]<br />Managed ROOT\pom.xml [Added dependency joda-time:joda-time:1.6]<br />Managed ROOT\pom.xml [Added dependency javax.servlet.jsp:jsp-api:2.1]<br />Managed ROOT\pom.xml<br />Managed ROOT\pom.xml [Added dependency com.google.gwt:gwt-servlet:2.1.0]<br />Managed ROOT\pom.xml [Added dependency com.google.gwt:gwt-user:2.1.0]<br />Managed ROOT\pom.xml [Added dependency org.json:json:20090211]<br />Managed ROOT\pom.xml [Added dependency com.googlecode.gwt.inject:gin:1.0]<br />Managed ROOT\pom.xml [Added dependency javax.validation:validation-api:1.0.0.GA]<br />Managed ROOT\pom.xml [Added dependency xalan:xalan:2.7.1]<br />Managed ROOT\pom.xml<br /><br /><br /></pre><br /><br />Roo managed the maven pom files with the gwt dependency files. We dont have to update the dependency section manually.<br /><br /><pre name="code" class="java"><br /><br />Created SRC_MAIN_WEBAPP\WEB-INF\spring<br />Created SRC_MAIN_WEBAPP\WEB-INF\spring\webmvc-config.xml<br />Created SRC_MAIN_WEBAPP\WEB-INF\web.xml<br />Managed SRC_MAIN_WEBAPP\WEB-INF\web.xml<br /><br /></pre><br /><br />Generated web.xml and webmvn-config.xml for the Server side configuration. The web.xml contains all the servlet mapping and Spring application context loading defined. The applicationContext.xml file gets created when you create the roo project using the New Roo Project wizard, but the file will not have any details about the persistence mechanism.<br /><br />In addition to the Maven POM Management, Spring Web MVC. Roo generates a basic GWT classes required for a Master/Detail layout web application.<br /><br /><ul><li>ApplicationScaffold.gwt.xml - GWT xml file with Entry point class defined.<br /></li><li>Client Scaffold Package - Roo by default generates classes for viewing the application on a Desktop browser and Mobile Browser. There will be classes with Desktop and Mobile in the class name for the UI.<br /></li><li>Client Scaffold UI Package - Contains basic ui boxes.<br /></li><li>Client Scaffold IOC Classes to Inject dependencies using Guice/Gin. - Contains Injector classes for Desktop and Mobile to return the respective Application as the entry point.<br /></li><li>Client Managed Activities - Contains ApplicationMasterActivities and ApplicationDetailActivities</li></ul><br /><span style="font-weight: bold;">Adding persistence Support</span><br /><br />Now that we have the basic project structure created we can add persistence support. Roo supports adding different types of Persistence mechanism and database. For example if you want to use Hibernate with in memory database.<br /><br /><pre name="code" class="java"><br />persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY<br />Managed SRC_MAIN_RESOURCES\META-INF\spring\applicationContext.xml<br />Created SRC_MAIN_RESOURCES\META-INF\persistence.xml<br />Created SRC_MAIN_RESOURCES\META-INF\spring\database.properties<br />Managed ROOT\pom.xml [Added dependency org.hsqldb:hsqldb:1.8.0.10]<br />Managed ROOT\pom.xml [Added dependency org.hibernate:hibernate-core:3.5.5-Final]<br />Managed ROOT\pom.xml [Added dependency org.hibernate:hibernate-entitymanager:3.5.5-Final]<br />Managed ROOT\pom.xml [Added dependency org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.0.Final]<br />Managed ROOT\pom.xml [Added dependency org.hibernate:hibernate-validator:4.1.0.Final]<br />Managed ROOT\pom.xml [Added dependency cglib:cglib-nodep:2.2]<br />Managed ROOT\pom.xml [Added dependency javax.transaction:jta:1.1]<br />Managed ROOT\pom.xml [Added dependency org.springframework:spring-jdbc:${spring.version}]<br />Managed ROOT\pom.xml [Added dependency org.springframework:spring-orm:${spring.version}]<br />Managed ROOT\pom.xml [Added dependency commons-pool:commons-pool:1.5.4]<br />Managed ROOT\pom.xml [Added dependency commons-dbcp:commons-dbcp:1.3]<br />Managed ROOT\pom.xml<br /><br /></pre><br /><br />We can see that roo modified the applicationContext.xml with dataSource information, added a persistence.xml file with the hibernate properties, database.properties file with database details and updated the pom file with all the dependencies.<br /><br /><span style="font-weight: bold;">Adding Domain Objects</span><br /><br />From the roo prompt do the following,<br /><br /><ore name="code" class="java"><br />entity --class ~.domain.Contact<br />Created SRC_MAIN_JAVA\com\roo\gwt\domain<br />Created SRC_MAIN_JAVA\com\roo\gwt\domain\Contact.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\domain\Contact_Roo_Configurable.aj<br />Created SRC_MAIN_JAVA\com\roo\gwt\domain\Contact_Roo_Entity.aj<br />Created SRC_MAIN_JAVA\com\roo\gwt\domain\Contact_Roo_ToString.aj<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\activity\ContactActivitiesMapper.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\activity\ContactEditActivityWrapper.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\activity\ContactDetailsActivity.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\activity\ContactListActivity.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactMobileListView.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactListView.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactListView.ui.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactDetailsView.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactDetailsView.ui.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactMobileDetailsView.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactMobileDetailsView.ui.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactEditView.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactEditView.ui.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactMobileEditView.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactMobileEditView.ui.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactProxyRenderer.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactSetEditor.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactSetEditor.ui.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactListEditor.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ContactListEditor.ui.xml<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\request\ContactProxy.java<br />Created SRC_MAIN_JAVA\com\roo\gwt\client\managed\request\ContactRequest.java<br />Managed SRC_MAIN_JAVA\com\roo\gwt\client\managed\request\ApplicationEntityTypesProcessor.java<br />Managed SRC_MAIN_JAVA\com\roo\gwt\client\managed\request\ApplicationRequestFactory.java<br />Managed SRC_MAIN_JAVA\com\roo\gwt\client\managed\ui\ApplicationListPlaceRenderer.java<br />Managed SRC_MAIN_JAVA\com\roo\gwt\client\managed\activity\ApplicationMasterActivities.java<br />Managed SRC_MAIN_JAVA\com\roo\gwt\client\managed\activity\ApplicationDetailsActivities.java<br />~.domain.Contact<br /><br /><br />This generates lot of classes which belong to different layers of a GWT Application,<br /><br /><span style="font-weight: bold;">Activities </span><br /><br />ContactActivitiesMapper<br />ContactEditActivityWrapper<br />ContactDetailsActivity<br />ContactListActivity<br /><br /><span style="font-weight: bold;">UI Binder</span><br /><br />ContactMobileListView<br />ContactListView.ui.xml<br />ContactDetailsView<br />ContactDetailsView.ui.xml<br />ContactMobileDetailsView<br />ContactMobileDetailsView.ui.xml<br />ContactEditView<br />ContactEditView.ui.xml<br />ContactMobileEditView<br />ContactMobileEditView.ui.xml<br />ContactSetEditor<br />ContactSetEditor.ui.xml<br />ContactListEditor<br />ContactListEditor.ui.xml<br /><br /><span style="font-weight: bold;">Request Factory</span><br />ContactProxy<br />ContactRequest<br /><br />To understand more about these different terminologies and how they fit into the GWT Architecture, please read this link <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html">http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html<br /></a><br /><br />Now lets add some fields to the Contact pojo object<br /><br /><pre name="code" class="java"><br />field string --fieldName name --notNull<br /></pre><br /><br />This will again update all the ui classes, request factory classes and aspectj classes to incorporate the new field.<br /><br />Lets compile the project using GWT Compile from the toolbar. GWT toolkit should compile all combinations of the application without any errors.<br /><br /><pre name="code" class="java"><br />Compiling module com.roo.gwt.ApplicationScaffold<br />Compiling 12 permutations<br />Compiling permutation 0...<br />Compiling permutation 1...<br />Compiling permutation 2...<br />Compiling permutation 3...<br />Compiling permutation 4...<br />Compiling permutation 5...<br />Compiling permutation 6...<br />Compiling permutation 7...<br />Compiling permutation 8...<br />Compiling permutation 9...<br />Compiling permutation 10...<br />Compiling permutation 11...<br />Compile of permutations succeeded<br />Linking into C:\STS_BLOG\workspace\Roo_GWT\target\Roo_GWT-0.1.0.BUILD-SNAPSHOT\applicationScaffold<br />Link succeeded<br />Compilation succeeded -- 90.265s<br /><br /></pre><br /><br />Now run the application as a Web Application ( Right Click-> Run As -> Web Application). From the development mode view double click the url which will launch the application in your default browser. You can see the application as shown below.<br /><br /></ore><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC4zK8tojHZHT-eQC3M1ixdLsVDUf_yfhrn5nTySpW3UO-aUctdBcazi29tuOdlMnVd9JTWp_vnhDoZHkuxkRGzXbK5uYxqjBPTqQNqxnU1M-m57nhDBtvivc9oGUG3fivw0hn1E3bPhQU/s1600/STS_WelcomePage.jpg"><img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 206px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC4zK8tojHZHT-eQC3M1ixdLsVDUf_yfhrn5nTySpW3UO-aUctdBcazi29tuOdlMnVd9JTWp_vnhDoZHkuxkRGzXbK5uYxqjBPTqQNqxnU1M-m57nhDBtvivc9oGUG3fivw0hn1E3bPhQU/s320/STS_WelcomePage.jpg" alt="" id="BLOGGER_PHOTO_ID_5541382139849956722" border="0" /></a><br />You can click on Create Contact and Add new contact like below<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc9W48K7l0mmmpXBeht0L1zhkLVT9q0bPM2sHv27vm4O4BOv6SS2mlRHJOUbXeTeOdg2kQgWf7pOp3Wz3UaIOh06WKi_CEHno6SP-nGYZk4jlmUprjfh9H3gpr1CYBDljoalcwtH5P7bEp/s1600/STS_WelcomePage.jpg"><img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 206px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc9W48K7l0mmmpXBeht0L1zhkLVT9q0bPM2sHv27vm4O4BOv6SS2mlRHJOUbXeTeOdg2kQgWf7pOp3Wz3UaIOh06WKi_CEHno6SP-nGYZk4jlmUprjfh9H3gpr1CYBDljoalcwtH5P7bEp/s320/STS_WelcomePage.jpg" alt="" id="BLOGGER_PHOTO_ID_5541382575633651122" border="0" /></a><br />We have written no queries, no business logic for the Contact object. But we got the Create contact , contact list, edit contact. This is where Roo comes in really handy. It generates a default set of queries, ui when we gave the commands "field string --fieldName name --notNull" Roo updates the ContactProxy object with the new field.<br /><br /><span style="font-weight: bold;">Where are the queries</span><br /><br />If you look at the domain package for the Contact object ( disable all the filters on the package explorer as by default only java classes are shown for a package ) you will find .aj files with *Roo_Configurable.aj, *_Roo_Entity.aj, *_Roo_JavaBean.aj, *_Roo_ToString.aj files.<br /><br />Specifically Contact_Roo_Entity.aj file will have all the query for interacting with the database.<br /><br /><pre name="code" class="java"><br /> public static final EntityManager Contact.entityManager() {<br /> EntityManager em = new Contact().entityManager;<br /> if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");<br /> return em;<br /> }<br /> <br /> public static long Contact.countContacts() {<br /> return entityManager().createQuery("select count(o) from Contact o", Long.class).getSingleResult();<br /> }<br /> <br /> public static List<contact> Contact.findAllContacts() {<br /> return entityManager().createQuery("select o from Contact o", Contact.class).getResultList();<br /> }<br /> <br /> public static Contact Contact.findContact(Long id) {<br /> if (id == null) return null;<br /> return entityManager().find(Contact.class, id);<br /> }<br /> <br /> public static List<contact> Contact.findContactEntries(int firstResult, int maxResults) {<br /> return entityManager().createQuery("select o from Contact o", Contact.class).setFirstResult(firstResult).setMaxResults(maxResults).getResultList();<br /> }<br /></contact></contact></pre><br /><br />These methods return the required data to the UI via the RequestFactory as ContactProxy Objects. ( You will understand this if you have read the GWT RequestFactory Article ). The methods in the aj files can be overwritten in the Contact entity class in which case Roo will remove the method from the .aj file. (Read more on this here <a href="http://static.springsource.org/spring-roo/reference/html-single/index.html">http://static.springsource.org/spring-roo/reference/html-single/index.html</a> )<br /><br />Overall, Roo is pretty good at generating and maintaining all the boiler plate code which is a painful job to write. But it can only generate based on a simple application structure. Not all applications are just Master/Detail layout.<br /><br /><span style="font-weight: bold;">How do i use Service Layer with the Request Factory</span><br /><br />According to GWT 2.1 you cant do this as RequestFactory is tightly bound with the Domain Driven Development approach. According to google service layer approach is going to be supported in GWT 2.1.1.KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com1tag:blogger.com,1999:blog-8961178336635312429.post-14955726687515863012009-07-15T22:45:00.000-07:002009-07-15T23:09:37.098-07:00Eclipse RCP : Single instance of RCP Application<div style="text-align: justify;">There are methods of maintaining a single instance of an application. Most often the application creates a lock file and holds on to it during the lifecycle of the application.<br /></div><br /><div style="text-align: justify;">A new instance of the application will try to find this file and if it exists, the application will try to show the existing instance to the user, preventing from creating whole new instance of the application. One drawback of this approach will be if the application crashes leaving the lock file. The user has to manually delete the file (or application can try deleting this file )<br /></div><div style="text-align: justify;">The same can be achieved via opening a server socket when the application is opened. Now how do we do it for a simple RCP Application.<br /></div><br /><br /><pre name="code" class="java"><br />/*<br /> * (non-Javadoc)<br /> * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)<br /> */<br /> public Object start(final IApplicationContext context)<br /> {<br /> if (!checkServerPort())<br /> {<br /> try<br /> {<br /> final ServerSocket server = new ServerSocket(5000);<br /><br /> serverThread = new Thread(new Runnable()<br /> {<br /> @Override<br /> public void run()<br /> {<br /> boolean socketClosed = false;<br /> while (!socketClosed)<br /> {<br /> if (server.isClosed())<br /> {<br /> socketClosed = true;<br /> }<br /> else<br /> {<br /> try<br /> {<br /> Socket client = server.accept();<br /> BufferedReader in = new BufferedReader(new InputStreamReader(client<br /> .getInputStream()));<br /> new UIJob("Reopening the app...")<br /> {<br /> @Override<br /> public IStatus runInUIThread(IProgressMonitor monitor)<br /> {<br /> advisor.getWindowAdvisor().handleEvent(null);<br /> return null;<br /> }<br /> }.schedule();<br /><br /> /**<br /> * if (SINGLE_INSTANCE_SHARED_KEY.trim().equals(message.trim())) {<br /> * System.out.println("Receiving message"); }<br /> */<br /> in.close();<br /> client.close();<br /> }<br /> catch (IOException ex)<br /> {<br /> socketClosed = false;<br /> }<br /> }<br /> }<br /> }<br /> });<br /> serverThread.start();<br /> }<br /> catch (IOException ex)<br /> {<br /> ex.printStackTrace();<br /> }<br /> }<br /> else<br /> {<br /> try<br /> {<br /> Socket clientSocket = new Socket(InetAddress.getLocalHost(), 5000);<br /> OutputStream out = clientSocket.getOutputStream();<br /> out.write(SINGLE_INSTANCE_SHARED_KEY.getBytes());<br /> out.close();<br /> clientSocket.close();<br /> }<br /> catch (UnknownHostException ex)<br /> {<br /> ex.printStackTrace();<br /> }<br /> catch (IOException ex)<br /> {<br /> ex.printStackTrace();<br /> }<br /> return IApplication.EXIT_OK;<br /> }<br /> final Display display = PlatformUI.createDisplay();<br /> try<br /> {<br /><br /> final int returnCode = PlatformUI.createAndRunWorkbench(display, advisor);<br /> if (returnCode == PlatformUI.RETURN_RESTART)<br /> {<br /> return IApplication.EXIT_RESTART;<br /> }<br /> return IApplication.EXIT_OK;<br /> }<br /> finally<br /> {<br /> display.dispose();<br /> }<br /> }<br /><br /> private boolean checkServerPort()<br /> {<br /> try<br /> {<br /> new Socket("localhost", 5000);<br /> }<br /> catch (IOException ex)<br /> {<br /> return false;<br /> }<br /> return true;<br /> }<br /><br /> /*<br /> * (non-Javadoc)<br /> * @see org.eclipse.equinox.app.IApplication#stop()<br /> */<br /> public void stop()<br /> {<br /> final IWorkbench workbench = PlatformUI.getWorkbench();<br /> if (workbench == null)<br /> {<br /> return;<br /> }<br /> final Display display = workbench.getDisplay();<br /> display.syncExec(new Runnable()<br /> {<br /> public void run()<br /> {<br /> if (!display.isDisposed())<br /> {<br /> workbench.close();<br /> }<br /> }<br /> });<br /> }<br /><br /></pre><br /><br />Now when the application is launched for the first time, it will open a server socket 5000 and will start listening on it. The next instance of the application will check the server port and if it is used already, it will create a client for that server socket and send a message to the server. <br /><br />When the server receives any message from the client, it will reopen the instance which created the server socket. <br /><br />The handleEvent method on the WorkbenchWindowAdvisor will have to have the following code..<br /><br /><pre name="code" class="java"><br /> /*<br /> * (non-Javadoc)<br /> * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)<br /> */<br /> @Override<br /> public void handleEvent(Event event)<br /> {<br /> Shell workbenchWindowShell = getWindowConfigurer().getWindow().getShell();<br /> workbenchWindowShell.setVisible(true);<br /> workbenchWindowShell.setActive();<br /> workbenchWindowShell.setFocus();<br /> workbenchWindowShell.setMinimized(false);<br /> }<br /></pre><br /><br />Now enjoy the single instance of the RCP application. This approach can be used for any java application.KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com2tag:blogger.com,1999:blog-8961178336635312429.post-71233355346097998542009-07-10T20:46:00.000-07:002009-07-24T13:13:44.406-07:00Eclipse RCP : Redirecting eclipse errors to log4j<div style="text-align: justify;">Its sometimes tedious to find the real exception occured when using an eclipse based application. Since it goes under the workspace/.metadata/.log file. It takes a while to figure this out. But most of the desktop application do write to a log file of its own. So when using eclipse using two log files to know about the application is kind of not nice.<br /></div><br /><div style="text-align: justify;">But still eclipse provides a way to listen to the log messages of its own. So if the application uses its own logging , it can listen to the eclipse log and add it to its own logger. Here we will look at connecting eclipse log messages to the log4j logger.<br /></div><br /><div style="text-align: justify;">Eclipse Platform provides a method to add listeners Platform.addLogListener(ILogListener);<br /></div><br /><div style="text-align: justify;">So how do we add the listener to the Platform. In the Activator of the application plugin's start method, add the following.<br /></div><br /><pre name="code" class="java"><br />public class Activator extends AbstractUIPlugin {<br /><br /> private ILogListener listener;<br /><br /><br /> @Override<br /> public void start(final BundleContext context) throws Exception {<br /> super.start(context);<br /> plugin = this;<br /> listener = new Listener();<br /> Platform.addLogListener(listener);<br /> }<br /><br /> @Override<br /> public void stop(final BundleContext context) throws Exception {<br /> Platform.removeLogListener(listener);<br /> listener = null;<br /> plugin = null;<br /> super.stop(context);<br /> }<br /><br />}<br /></pre><br /><br /><div style="text-align: justify;">Now every error/warning eclipse logs to its .log file under .metadata directory will be sent to the log listener. How does the log listener handle the events from the eclipse?<br /></div><br /><pre name="code" class="java"><br /> package com.logging;<br /> public class Listener implements ILogListener {<br /> private static final Logger LOGGER = Logger.getLogger(Listener.class.getName());<br /><br /> @Override<br /> public void logging(final IStatus status, final String plugin) {<br /> if (status.getSeverity() == IStatus.WARNING) {<br /> if (status.getException() == null) {<br /> LOGGER.warn(status.getMessage());<br /> } else {<br /> LOGGER.warn(status.getMessage() + status.getException());<br /> }<br /> } else if (status.getSeverity() == IStatus.ERROR) {<br /> if (status.getException() == null) {<br /> LOGGER.error(status.getMessage()); <br /> } else {<br /> LOGGER.error(status.getMessage()+status.getException());<br /> }<br /> }<br /> }<br /> }<br /></pre><br /><br /><div style="text-align: justify;">Now all the eclipse errors and warnings will go to the logger which is configured for Listener.class.getName().<br /></div><br /><div style="text-align: justify;">To get all the log messages from the eclipse. the log4j.properties<br /></div><br />log4j.category.com.logging.Listener=all<br /><br /><div style="text-align: justify;">This will log all the errors and warnings from the eclipse application to the log4j's log file or console as configured.</div>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com3tag:blogger.com,1999:blog-8961178336635312429.post-26779755424542044262009-07-06T22:56:00.000-07:002009-07-07T13:17:06.253-07:00Eclipse RAP : Custom Widget developmentIt took a while to understand and create a custom widget but finally i could do it. I wanted to create a custom widget to draw sequence of svg graphics. I followed the Custom widget development at the RAP help site. It helped me to get a good start but since i was trying to do SVG it didnt really work at my first attempt..(i know... nothing works at the first attempt).<br /><br />The SVG support i wanted to create was something like below.<br /><br /><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxtTLJQjYhX6_Nc8JjhEd0hIaoWFMrvmMwOoM4be8V0TYQQVske9JjG6SkK8ctNgNFtROoi8untQOrUufg8lw' class='b-hbp-video b-uploaded' frameborder='0'></iframe><br /><br />Here is what i did to create a custom widget.<br /><br />1. Create a new plugin project and name it like com.xyz.project.mywidget<br /> This is not mandatory but its good to call the plugin as the widget name.<br /><br />2. Create a package com.xyz.project.mywidget<br /> This package will contain the server side, client side and API resource classes. Just follow as explained in the RAP help.<br /><br />3. Create the server side Widget class , i wanted a widget to send events to the server and also behave as a selection provider when a image is clicked. So i extended SWT Composite and implemented ISelectionProvider.<br /><br /><pre name="code" class="java"><br />public class MyWidget extends Composite implements ISelectionProvider {<br /><br /> /**<br /> * for showing multiple images on the widget<br /> */<br /> private String[] images;<br /><br /> /**<br /> * To get the selection back from the client.<br /> */<br /> int selectionIndex;<br /><br /> /**<br /> * Listeners<br /> */<br /> private ListenerList listeners = new ListenerList();<br /><br /> /**<br /> * Selection.<br /> */<br /> private ISelection selection;<br /><br /> private String selectedImage;<br /><br /> public MyWidget(Composite parent) {<br /> super(parent, SWT.NONE);<br /> }<br /><br /> public String[] getImages() {<br /> return images;<br /> }<br /><br /> public void setImages(String[] parts) {<br /> this.images = parts;<br /> }<br /><br /> @Override<br /> public void setLayout(Layout layout) {<br /> super.setLayout(new FillLayout());<br /> }<br /><br /> public String getSelectedImage() {<br /> return selectedImage;<br /> }<br /><br /> public void setSelectedImage(String selectedPart) {<br /> this.selectedImage = selectedPart;<br /> if (selectedPart != null) {<br /> selectionIndex = Integer.parseInt(selectedPart);<br /> setSelection(new StructuredSelection(images[selectionIndex / 2]));<br /> }<br /> }<br /><br /> public void addSelectionChangedListener(ISelectionChangedListener listener) {<br /> listeners.add(listener);<br /> }<br /><br /> public ISelection getSelection() {<br /> return selection;<br /> }<br /><br /> public void removeSelectionChangedListener(<br /> ISelectionChangedListener listener) {<br /> listeners.remove(listener);<br /> }<br /><br /> public void setSelection(ISelection selection) {<br /> this.selection = selection;<br /> Object[] list = listeners.getListeners();<br /> for (int i = 0; i < list.length; i++) {<br /> ((ISelectionChangedListener) list[i])<br /> .selectionChanged(new SelectionChangedEvent(this, selection));<br /> }<br /> }<br />}<br /><br /></pre><br /><br />Follow this post for how to implement ISelectionProvider - <a href="http://random-eclipse-tips.blogspot.com/2009/02/eclipse-how-to-implement.html">http://random-eclipse-tips.blogspot.com/2009/02/eclipse-how-to-implement.html</a><br /><br />Now that the server side, widget is ready, we need the client side widget code, the qooxdoo javascript code. Read the qooxdoo explanation in RAP custom widget tutorial and follow it, it gives you a basic idea of what to do. <br /><br /><br /><pre name="code" class="java"> qx.Class.define( "com.xyz.project.MyWidget", {<br /> extend: qx.ui.layout.CanvasLayout,<br /> <br /> construct: function( id ) {<br /> this.base( arguments );<br /> this.setHtmlAttribute("id",id);<br /> this._id = id; <br /> },<br /> <br /> properties : {<br /> images : {<br /> init : "",<br /> apply : "load"<br /> },<br /><br /> members : { <br /> load : function() {<br /> var current = this.getParts()[0];<br /> if( current != null && current != "" ) {<br /> qx.ui.core.Widget.flushGlobalQueues();<br /> var id = document.getElementById( this._id );<br /> var wm = org.eclipse.swt.WidgetManager.getInstance();<br /> var designWidgetId = wm.findIdByWidget( this);<br /> var newParts = this.getParts(); <br /> var current = null;<br /> var image = 1;<br /> if(this.__paper == null ) {<br /> this.__paper = Raphael(id, newParts.length*100, 480);<br /> startx = 10;<br /> starty = 10;<br /> width = 100;<br /> height=25;<br /> curve=10;<br /> var part=0, colorhue = .6 || Math.random(), <br /> color = "hsb(" + [colorhue, 1, .75] + ")";<br /> var selectionColor = "#d54";<br /> var currentSelection = null;<br /> var detail = this.__paper.rect(startx, starty+height+5, 200, 100, 5).attr({fill: "#d54" , stroke: "#474", "stroke-width": 2}).hide(); <br /> label0 = this.__paper.text(startx+20,starty+height+10,"ID : ").hide();<br /> label1 = this.__paper.text(startx+20,starty+height+25,"Other : ").hide();<br /> for (part=0;part<newParts.length;part++) <br /> {<br /> (function(paper,part,type){<br /> var c = "#ccc";<br /> if(image==0) {<br /> if(type == "image1") {<br /> paper.image("./Part_icon_image1.png", startx, starty, width, height);<br /> }else if(type == "image2") {<br /> image("./Part_icon_image2.png", startx, starty, width, height);<br /> } <br /> } <br /> var label = paper.text(startx+25,starty+10,part).hide();<br /> paper.rect(startx,starty,width,height,curve).attr({stroke: c, fill: c, "fill-opacity": .4}).<br /> mouseover(<br /> function(){<br /> this.animate({"fill-opacity": .75}, 500); <br /> detail.show().animate({x: 10+(width*part), y: starty+height+5}, 200 );<br /> label0.attr({text: "ID : "+newParts[part]}).show().animate({x: 40+(width*part), y: starty+height+10}, 200);<br /> label1.attr({text: "Other : "}).show().animate({x: 40+(width*part), y: starty+height+25}, 200);<br /> paper.safari();<br /> }).<br /> mouseout(<br /> function(){ <br /> this.animate({"fill-opacity": .25}, 500); <br /> detail.hide();<br /> label0.hide();<br /> label1.hide();<br /> paper.safari();<br /> }).<br /> click(<br /> function(){<br /> if(currentSelection != null ) {<br /> currentSelection.attr({fill:c});<br /> }<br /> currentSelection = this;<br /> currentSelection.attr({fill:selectionColor});<br /> var req = org.eclipse.swt.Request.getInstance(); <br /> req.addParameter( designWidgetId +".selectedImage", part ); <br /> req.send();<br /> });<br /> })(this.__paper,part,newParts[part]); <br /> startx+=width; <br /> } <br /> }} <br /> <br /> }, <br /> }<br />});<br /></pre><br /><br />Now that, whenever the setImages method is called on the server side widget, the client has to update the browser. But how does it interact, the server side widget and the client side widget get connected through two main classes, the API resource class and the LCA class. There are different ways of defining the LCA class but here i would just follow the simple approach as explained in the RAP help.<br /><br />First to create the API resource, we need to create a IResource implementation , In our case, MyWidgetResource as follows,<br /><br /><pre name="code" class="java"><br />public class DesignWidgetResource implements IResource {<br /> public String getCharset() {<br /> return HTML.CHARSET_NAME_ISO_8859_1;<br /> }<br /><br /> public ClassLoader getLoader() {<br /> return this.getClass().getClassLoader();<br /> }<br /><br /> public RegisterOptions getOptions() {<br /> return RegisterOptions.VERSION_AND_COMPRESS;<br /> }<br /><br /> public String getLocation() {<br /> return "com/xyz/project/mywidget/MyWidget.js";<br /> }<br /><br /> public boolean isJSLibrary() {<br /> return true;<br /> }<br /><br /> public boolean isExternal() {<br /> return false;<br /> }<br />}<br /></pre><br />you can just copy and paste the above code and replace the getLocation method to your .js file. Now the LCA, this can either be written in a pre defined package or can be done using getAdapter method in the widget class. I will follow the pre defined package which com.xyz.project.mywidget.internal.mywidgetkit and create MyWidgetLCA.java<br /><br /><br /><pre name="code" class="java"><br /><br />public class MyWidgetLCA extends AbstractWidgetLCA {<br /><br /> private static final String PARAM_SELECTED = "selectedImage";<br /><br /> private static final String PROP_IMAGES = "images";<br /><br /> private static final String JS_PROP_IMAGE = "images";<br /><br /> public void preserveValues(final Widget widget) {<br /> ControlLCAUtil.preserveValues((Control) widget);<br /> IWidgetAdapter adapter = WidgetUtil.getAdapter(widget);<br /> adapter.preserve(PROP_IMAGES, ((MyWidget) widget).getImages());<br /> // adapter.preserve(PROP_MOVE_RIGHT, ((DesignWidget) widget)<br /> // .getMoveRight());<br /> // only needed for custom variants (theming)<br /> WidgetLCAUtil.preserveCustomVariant(widget);<br /> }<br /><br /> /*<br /> * Read the parameters transfered from the client<br /> */<br /> public void readData(final Widget widget) {<br /> MyWidget myWidget = (MyWidget) widget;<br /> String location = WidgetLCAUtil.readPropertyValue(myWidget,<br /> PARAM_SELECTED);<br /> myWidget.setSelectedImage(location);<br /> }<br /><br /> /*<br /> * Initial creation procedure of the widget<br /> */<br /> public void renderInitialization(final Widget widget) throws IOException {<br /> JSWriter writer = JSWriter.getWriterFor(widget);<br /> String id = WidgetUtil.getId(widget);<br /> writer.newWidget("com.xyz.project.mywidget.MyWidget",<br /> new Object[] { id });<br /> writer.set("appearance", "composite");<br /> writer.set("overflow", "hidden");<br /> ControlLCAUtil.writeStyleFlags((MyWidget) widget);<br /> }<br /><br /> public void renderChanges(final Widget widget) throws IOException {<br /> MyWidget gmap = (MyWidget) widget;<br /> ControlLCAUtil.writeChanges(gmap);<br /> JSWriter writer = JSWriter.getWriterFor(widget);<br /> writer.set(PROP_IMAGES, JS_PROP_IMAGE, gmap.getImages());<br /> // only needed for custom variants (theming)<br /> WidgetLCAUtil.writeCustomVariant(widget);<br /> }<br /><br /> public void renderDispose(final Widget widget) throws IOException {<br /> JSWriter writer = JSWriter.getWriterFor(widget);<br /> writer.dispose();<br /> }<br /><br /> public void createResetHandlerCalls(String typePoolId) throws IOException {<br /> }<br /><br /> public String getTypePoolId(Widget widget) {<br /> return null;<br /> }<br /><br />}<br /></pre><br /><br />Here, the LCA class is the important class which communicates between the server code and client script. The selection on the client sends an event to the server through the LCA in the readData method. The client code will use org.eclipse.swt.Request.getInstance() to send the request to the server when an image is clicked on the Widget.<br /><br />Now we got the both the resource and LCA ready. we need to create an resources extension point and add the MyWidgetResource classes.<br /><pre name="code" class="java"> <extension<br /> point="org.eclipse.rap.ui.resources"><br /> <resource<br /> class="com.xyz.project.mywidget.MyWidgetResource"><br /> </resource><br /> </extension><br /></pre><br /><br />ok..we have a basic setup ready, what is the Raphael stuff on the Qooxdoo javascript. Raphael is a Javascript based SVG library which helps creating different SVG based graphics. For more details on that visit <a href="http://http://raphaeljs.com/">http://raphaeljs.com/</a>. The demos explain a lot about the library. How do we add an external javascript resource into the myWidget implementation. <br /><br />1. Create a RaphaelAPIResource similar to the one we created for MyWidget as MyWidgetResource.<br /><pre name="code" class="java"><br />public class RaphaelAPIResource implements IResource {<br /><br /> private String location;<br /><br /> public String getCharset() {<br /> return HTML.CHARSET_NAME_ISO_8859_1;<br /> }<br /><br /> public ClassLoader getLoader() {<br /> return this.getClass().getClassLoader();<br /> }<br /><br /> public String getLocation() {<br /> location = "http://raphaeljs.com/raphael.js";<br /> return location;<br /> }<br /><br /> public RegisterOptions getOptions() {<br /> return RegisterOptions.VERSION;<br /> }<br /><br /> public boolean isExternal() {<br /> return true;<br /> }<br /><br /> public boolean isJSLibrary() {<br /> return true;<br /> }<br /><br />}<br /></pre><br /><br />and add the resources extension to the existing extension point we used as following.<br /><pre name="code" class="xml"> <extension<br /> point="org.eclipse.rap.ui.resources"><br /> <resource<br /> class="com.biologistics.gd.design.RaphaelAPIResource"><br /> </resource><br /> <resource<br /> class="com.biologistics.gd.design.DesignWidgetResource"><br /> </resource><br /> </extension><br /></pre><br /><br />Since we are displaying images on the client side , we need the images also as resources sent to the client. we have to create http.registryresources to use aliases for the images. In this case, we are referring to Part_icon_image1.png and Part_icon_image2.png as alias in the javascript.<br /><br /><pre name="code" class="xml"> <extension<br /> point="org.eclipse.equinox.http.registry.resources"><br /> <resource<br /> alias="/Part_icon_image1.png"<br /> base-name="branding/Part_icon_image1.png"><br /> </resource><br /> <resource<br /> alias="/Part_icon_image2.png"<br /> base-name="original/Part_icon_image2.png"><br /> </resource><br /> </extension><br /></pre><br /><br />Now we can create a view with MyWidget as a child and setImages on that.<br /><br /><pre name="code" class="java"> public void createPartControl(final Composite parent) {<br /> widget = new MyWidget(parent);<br /> widget.setParts(new String[]{"image1","image2"});<br /> getSite().setSelectionProvider(widget); <br /> }<br /></pre><br /><br />Will be glad to help !KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com2tag:blogger.com,1999:blog-8961178336635312429.post-39348945433271203342009-03-05T23:35:00.000-08:002009-03-05T23:46:49.498-08:00Quick Tips: Storing preferences and settings per user in a RCP applicationEclipse RCP applications store the prefrences and settings in the workspace. When a RCP application is exported, the workspace is opened within the application folder unless the workspace location is overridden. This will make every user who uses the application to use the same preferences. To enable the preferences and workbench state to be user specific, the default location of the workspace can be configured in the config.ini file as follows.<br /><br /><pre name="code" class="java"><br />osgi.instance.area.default=@user.home/eclipseworkspace<br /></pre><br /><br />Now the preferences and other dialog settings will be written in the user's own workspaces.KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-68055691909240287132009-03-05T23:10:00.000-08:002009-03-05T23:34:38.870-08:00Quick Tip: Save and Restore the perspective layoutTo restore the perspctive to the last modified state, eclipse stores the workbench state to a file called workbench.xml. To enable the save and restore layout, the IWorkbenchConfigurer must be set in the ApplicationWorkbenchAdvisor.<br /><br /><pre name="code" class="java"><br />public void initialize(IWindowConfigurer configurer)<br />{<br />configurer.setSaveAndRestore(true);<br />}<br /></pre>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-40094052583042456492009-03-02T21:55:00.001-08:002009-03-02T22:31:09.349-08:00Eclipse : Writing to the console in a RCP ApplicationWhen you want to add console message to the eclipse console view, there is no easiest way to do this. The sysout/syserr messages will go on the console where you have the application if you run it with -consoleLog option.<br /><br />How do we show the messages on the console view eclipse provides. First of all we have to add the console view to the perspective. The console view is part of the org.eclipse.ui.console plugin, so add it to the dependencies if you dont have it already.<br /><br />Now add the ConsoleView to the perspective in the createInitialLayout method ( the following snippet is written with the RCP Mail example )<br /><br /><pre name="code" class="java"><br />public void createInitialLayout(IPageLayout layout) {<br /> String editorArea = layout.getEditorArea();<br /> layout.setEditorAreaVisible(false);<br /><br /> layout.addStandaloneView(NavigationView.ID, false, IPageLayout.LEFT,<br /> 0.25f, editorArea);<br /> IFolderLayout folder = layout.createFolder("messages", IPageLayout.TOP,<br /> 0.5f, editorArea);<br /> folder.addPlaceholder(View.ID + ":*");<br /> folder.addView(View.ID);<br /><br /> IFolderLayout consoleFolder = layout.createFolder("console",<br /> IPageLayout.BOTTOM, 0.65f, "messages");<br /> consoleFolder.addView(IConsoleConstants.ID_CONSOLE_VIEW);<br /> layout.getViewLayout(NavigationView.ID).setCloseable(false);<br /> }<br /></pre><br /><br />Now if you run the application you can see the console view at the bottom of the Messages view of the RCP Mail application. But now there are no open consoles on the console view. Now let us take an example, whenever a Messages view is opened we want to write something to the console.<br /><br /><pre name="code" class="java"><br />public class OpenViewAction extends Action {<br /><br /> private final IWorkbenchWindow window;<br /> private int instanceNum = 0;<br /> private final String viewId;<br /> MessageConsole messageConsole;<br /><br /> public OpenViewAction(IWorkbenchWindow window, String label, String viewId) {<br /> this.window = window;<br /> this.viewId = viewId;<br /> setText(label);<br /> // The id is used to refer to the action in a menu or toolbar<br /> setId(ICommandIds.CMD_OPEN);<br /> // Associate the action with a pre-defined command, to allow key<br /> // bindings.<br /> setActionDefinitionId(ICommandIds.CMD_OPEN);<br /> setImageDescriptor(com.blog.sample.Activator<br /> .getImageDescriptor("/icons/sample2.gif"));<br /><br /> }<br /><br /> public void run() {<br /> if (window != null) {<br /> try {<br /> int instance = instanceNum++;<br /> window.getActivePage().showView(viewId,<br /> Integer.toString(instance),<br /> IWorkbenchPage.VIEW_ACTIVATE);<br /><br /> messageConsole = getMessageConsole();<br /> MessageConsoleStream msgConsoleStream = messageConsole<br /> .newMessageStream();<br /><br /> ConsolePlugin.getDefault().getConsoleManager().addConsoles(<br /> new IConsole[] { messageConsole });<br /><br /> msgConsoleStream.println(viewId + Integer.toString(instance));<br /><br /> } catch (PartInitException e) {<br /> MessageDialog.openError(window.getShell(), "Error",<br /> "Error opening view:" + e.getMessage());<br /> }<br /> }<br /> }<br /><br /> private MessageConsole getMessageConsole() {<br /> if (messageConsole == null) {<br /> messageConsole = new MessageConsole("RCPMail", null);<br /> ConsolePlugin.getDefault().getConsoleManager().addConsoles(<br /> new IConsole[] { messageConsole });<br /> }<br /><br /> return messageConsole;<br /> }<br /><br />}<br /></pre><br /><br />Now every new view opened will write the ViewID to the RCPMail console we created.<br /><br />Have fun!KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-7512911564992848862009-02-26T22:46:00.000-08:002009-02-26T23:17:15.354-08:00Quick Tip : Adding SWT controls to the Trim Area<div style="text-align: justify;">Sometimes RCP applications needs to show a label or some swt control on the trim area (outer boundary of the workbench window ) for example in the status area, after the perspective switch bar area and so on.<br /></div><br /><div style="text-align: justify;">org.eclipse.ui.menus extension point allows to places command or control on the toolbar , menubar or on the trim area. For this post, if you want to add a control or command to the status area or the perspective switch area, use the following locationURI.<br /></div><br />For placing it on the status area - toolbar:org.eclipse.ui.trim.status this will place the control or command on the status area. ( You have to make sure the status area is made visible in the workbenchwindowadvisors preWindowOpen() method as<br /><br /><pre name="code" class="java"><br /> public void preWindowOpen() {<br /> IWorkbenchWindowConfigurer configurer = getWindowConfigurer();<br /> configurer.setInitialSize(new Point(600, 400));<br /> configurer.setShowCoolBar(true);<br /> configurer.setShowPerspectiveBar(true);<br /> configurer.setShowStatusLine(true);<br /> }<br /></pre><br /><br />For placing it on the perspective switch area - toolbar:org.eclipse.ui.trim.command2, this will add the control next to the perspective switch area.<br /><br />The extension point should create a menuContribution with the correct locationURI, and add the controls/commands to a toolbar.<br /><br /><pre name="code" class="xml"><br /> <extension<br /> point="org.eclipse.ui.menus"><br /> <menuContribution<br /> locationURI="toolbar:org.eclipse.ui.trim.command2"><br /> <toolbar<br /> id="com.blog.sample.toolbar1"><br /> <control<br /> class="com.blog.sample.WorkbenchWindowControlContribution1"><br /> </control><br /> </toolbar><br /> </menuContribution><br /> </extension><br /></pre><br /><br />Have fun !KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-52946241707494270492009-02-24T23:13:00.000-08:002009-02-24T23:23:43.570-08:00Eclipse : Minimizing the RCP App to the system tray.<div style="text-align: justify;">ApplicationWorkbenchWindowAdvisor of the RCP application can handle preWindowShellClose() and postWindowClose(). If you want the application to be stored to the system tray when closed, the preWindowClose event can be handled as below to add a system tray icon with Open and Exit actions which will open/exit the workbench.<br /></div><br /><pre name="code" class="java"><br /> @Override<br /> public boolean preWindowShellClose() {<br /> final TrayItem item = new TrayItem(<br /> Display.getCurrent().getSystemTray(), SWT.NONE);<br /> final Image image = Activator.getImageDescriptor("icons/mail.ico")<br /> .createImage();<br /> item.setImage(image);<br /> item.setToolTipText("RCPMail - Tray Icon");<br /> getWindowConfigurer().getWindow().getShell().setVisible(false);<br /> item.addSelectionListener(new SelectionAdapter() {<br /> public void widgetDefaultSelected(SelectionEvent e) {<br /> Shell workbenchWindowShell = getWindowConfigurer().getWindow()<br /> .getShell();<br /> workbenchWindowShell.setVisible(true);<br /> workbenchWindowShell.setActive();<br /> workbenchWindowShell.setFocus();<br /> workbenchWindowShell.setMinimized(false);<br /> image.dispose();<br /> item.dispose();<br /> }<br /> });<br /><br /> Shell workbenchWindowShell = getWindowConfigurer().getWindow()<br /> .getShell();<br /> // Create a Menu<br /> final Menu menu = new Menu(workbenchWindowShell, SWT.POP_UP);<br /> // Create the exit menu item.<br /> final MenuItem exit = new MenuItem(menu, SWT.PUSH);<br /> exit.setText("Exit");<br /><br /> // Create the open menu item.<br /> final MenuItem open = new MenuItem(menu, SWT.PUSH);<br /> open.setText("Open");<br /> // make the workbench visible in the event handler for exit menu item.<br /> open.addListener(SWT.Selection, new Listener() {<br /> public void handleEvent(Event event) {<br /> // Do a workbench close in the event handler for exit menu item.<br /> exit.addListener(SWT.Selection, new Listener() {<br /> public void handleEvent(Event event) {<br /> image.dispose();<br /> item.dispose();<br /> open.dispose();<br /> exit.dispose();<br /> menu.dispose();<br /> getWindowConfigurer().getWorkbenchConfigurer().getWorkbench()<br /> .close();<br /> }<br /> }); Shell workbenchWindowShell = getWindowConfigurer().getWindow()<br /> .getShell();<br /> workbenchWindowShell.setVisible(true);<br /> workbenchWindowShell.setActive();<br /> workbenchWindowShell.setFocus();<br /> workbenchWindowShell.setMinimized(false);<br /> image.dispose();<br /> item.dispose();<br /> open.dispose();<br /> exit.dispose();<br /> menu.dispose();<br /> }<br /> });<br /> item.addListener(SWT.MenuDetect, new Listener() {<br /> public void handleEvent(Event event) {<br /> menu.setVisible(true);<br /> }<br /> });<br /> // Do a workbench close in the event handler for exit menu item.<br /> exit.addListener(SWT.Selection, new Listener() {<br /> public void handleEvent(Event event) {<br /> image.dispose();<br /> item.dispose();<br /> open.dispose();<br /> exit.dispose();<br /> menu.dispose();<br /> getWindowConfigurer().getWorkbenchConfigurer().getWorkbench()<br /> .close();<br /> }<br /> });<br /> return false;<br /> }<br /></pre>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-48328506686390116992009-02-24T13:07:00.000-08:002009-02-24T14:38:47.433-08:00Equinox : Authenticate with Database Login using Equinox SecurityMost of the desktop applications require a authentication step when the application is started. Eclipse does not yet provide a login mechanism to authenticate the user. But the equinox security has it on the proposal to support login dialog based authentication. Till then, what would be the best way to do the authentication with existing equinox security features. Lets have a look at RCP Mail Template with a login dialog during start up.<br /><br /><div style="text-align: justify;">Equinox implements the standard Java Authentication and Authorization Service ( JAAS ) to authenticate and authorize. We will look at some realtime examples of how to do the authentication.<br /></div><br /><div style="text-align: justify;">Equinox supports extension login modules which can be configured via the loginmodule extension. The extension can be configured with nt login module, LDAP login modules from the sun security modules or can be configured with custom written LoginModules like RDBMSLoginModule, SecureStorage Logins and so on.<br /></div><br /><div style="text-align: justify;">The example from the org.eclipse.equinox.security.sample from the equinox cvs (org.eclipse.equinox/incubator/security/bundles/org.eclipse.equinox.security.sample ) /cvsroot/rt explains adding LDAP, WIN32 and other login modules to the application. Here in this example we will write a custom LoginModule which authenticates against a database connection.<br /><br />RDBMSLoginModule - The login modules has to implement LoginModule interface from javax security. The LoginModule contains initialize, login, logout, commit and abort methods. The initialize method gives the CallbackHanlder and other options.<br /><br />The Login Method which does the authentication has to be implemented against a database for this example.<br /><pre name="code" class="java"><br />public boolean login() throws LoginException<br />{<br /><br />if (callbackHandler == null)<br /> throw new LoginException("Error: no CallbackHandler available "<br /> + "to garner authentication information from the user");<br /><br />try<br />{<br /> // Setup default callback handlers.<br /> Callback[] callbacks = new Callback[] { new NameCallback("Username: "),<br /> new PasswordCallback("Password: ", false), new NameCallback("Database: ") };<br /><br /> callbackHandler.handle(callbacks);<br /><br /> String username = ((NameCallback) callbacks[0]).getName();<br /> String password = new String(((PasswordCallback) callbacks[1]).getPassword());<br /> String dbname = ((NameCallback) callbacks[2]).getName();<br /><br /> ((PasswordCallback) callbacks[1]).clearPassword();<br /><br /> success = rdbmsValidate(username, password,dbname); // This method should try to connect <br />//to the database with the given username,password, url and return true on success.<br /><br /> callbacks[0] = null;<br /> callbacks[1] = null;<br /><br /> if (!success)<br /> throw new LoginException("Authentication failed: Password does not match");<br /><br /> return (true);<br />}<br />catch (LoginException ex)<br />{<br /> throw ex;<br />}<br />catch (Exception ex)<br />{<br /> success = false;<br /> throw new LoginException(ex.getMessage());<br />}<br />}<br /></pre>The LoginModule is declared with org.eclipse.equinox.security.loginModule extension point.<br /><br /><pre name="code" class="xml"><br /><extension<br /> id="com.sample.login.RdbmsLoginModule"<br /> point="org.eclipse.equinox.security.loginModule"><br /> <loginModule<br /> class="com.sample.login.RdbmsLoginModule"><br /> </loginModule><br /></extension><br /></pre><br />The login method calls the callback handler which is configured in the plugin.xml via the extension org.eclipse.equinox.security.callbackHandler<br /><pre name="code" class="xml"><br /><extension<br /> id="com.sample.login.LoginDialogCallbackHandler"<br /> point="org.eclipse.equinox.security.callbackHandler"><br /><callbackHandler<br /> class="com.sample.login.LoginDialogCallbackHandler"><br /></callbackhandler><br /></extension><br /><br /><br /></pre>The call back handler is mapped to a configName in this case say RDBMS to a Dialog which takes username, password and the db url.<br /><br />The CallBackHandlerMapping is done as follows<br /><pre name="code" class="java"><br /><extension<br /> point="org.eclipse.equinox.security.callbackHandlerMapping"><br /><callbackHandlerMapping<br /> callbackHandlerId="com.sample.login.LoginDialogCallbackHandler"<br /> configName="RDBMS"><br /></callbackHandlerMapping><br /></extension><br /></pre><br /><div style="text-align: justify;">Once the rdbmsValidate method successfully connects to the database with the given values , a javax.security.auth.Subject can be constructed with the Credentials and Principals as an authenticated user.<br /></div><pre name="code" class="java"><br />private boolean rdbmsValidate(String user, String pass) throws Exception<br />{<br /><br /> Connection con;<br /> boolean passwordMatch = true;<br /><br /> try<br /> {<br /> Class.forName(driverClass);<br /> }<br /> catch (java.lang.ClassNotFoundException e)<br /> {<br /> System.err.print("ClassNotFoundException: ");<br /> System.err.println(e.getMessage());<br /> throw new LoginException("Database driver class not found: " + driverClass);<br /> }<br /><br /> try<br /> {<br /> if (debug)<br /> System.out.println("\t\t[RdbmsLoginModule] Trying to connect...");<br /><br /> con = DriverManager.getConnection(url, user, pass);<br /> if(con == null )<br /> passwordMatch = false;<br /> else<br /> //Construct a subject.<br /> } catch(Exception ex) {<br /> }<br /> return (passwordMatch)'<br />}<br /></pre><br />Now that all the extension points are made for the authentication. We need to call the LoginModule at the appropriate place on the application. Usually the Eclipse Application start method is a good place to keep the Authentication process.<br /><br />Create the LoginContext from the RDBMS callback handler defined in the plugin.xml.<br /><pre name="code" class="java"><br />public Object start(final IApplicationContext context) throws Exception<br />{<br /> String configName = Activator.getConfigurationName();<br /> URL configUrl = Activator.getBundleContext().getBundle().getEntry("jaas_config.txt");<br /> ILoginContext secureContext = LoginContextFactory.createContext(configName, configUrl);<br /> secureContext.registerListener(new ProgressMonitorListener());<br /> Integer result = null;<br /> final Display display = PlatformUI.createDisplay();<br /> try<br /> {<br /> result = (Integer) Subject.doAs(secureContext.getSubject(), getRunAction(display));<br /> }<br /> finally<br /> {<br /> display.dispose();<br /> secureContext.logout();<br /> }<br /> // TBD handle javax.security.auth.login.LoginException<br /><br /> if (result != null && PlatformUI.RETURN_RESTART == result.intValue())<br /> return EXIT_RESTART;<br /> return EXIT_OK;<br />}</pre><br /><br />Add the following methods to the Activator class of the plugin.<br /><pre name="code" class="java"><br /><br />private static final String CONFIG_PREF = "loginConfiguration";//$NON-NLS-1$<br /><br />private static final String CONFIG_DEFAULT = "other";<br /><br />public static BundleContext getBundleContext()<br />{<br /> return bundleContext;<br />}<br /><br />public static String getConfigurationName()<br />{<br /> return new DefaultScope().getNode(PLUGIN_ID).get(CONFIG_PREF, CONFIG_DEFAULT);<br />}<br /></pre><br /><div style="text-align: justify;">Finally the jaas_config.txt file which defines the RDBMS callback Handler name with the Login Module extension ( RDBMSLoginModule ) should be placed in the plugin's root folder.<br /></div><br /><pre name="code" class="java"><br />RDBMS {<br />org.eclipse.equinox.security.auth.module.ExtensionLoginModule required<br />extensionId="com.sample.login.RdbmsLoginModule"<br />debug=true;<br />};<br /></pre><br /></div>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-13296911265655036442009-02-18T22:26:00.001-08:002009-02-18T22:31:37.127-08:00Quick Tips : Opening the Eclipse Preferences with a specfic Preference Page.<div style="text-align: justify;">When we create PreferencePages in a Eclipse RCP applications, the window->Preferences menu item opens the preferences dialog and all the preferneces are shown in the Preferences window. How about showing a particular preference page from a toolbar button in a view / application.<br /></div><br />Before the command framework we can do it using the PreferenceUtil class like belore<br /><br /><pre name="code" class="java"><br />PreferencesUtil.createPreferenceDialogOn(shell, preferencePageId, displayedIds, data)<br /></pre><br /><br />But with the help of the command framework,it is way easy to do this task.<br /><br /><pre name="code" class="xml"><br /> <extension<br /> point="org.eclipse.ui.menus"><br /> <menuContribution<br /> locationURI="toolbar:com.blog.sample.ui.ButtonView"><br /> <command<br /> commandId="org.eclipse.ui.window.preferences"<br /> label="Preferences"<br /> style="push"><br /> <parameter<br /> name="preferencePageId"<br /> value="com.blog.sample.ui.CorePreferencePage"><br /> </parameter><br /> </command><br /> </menuContribution><br /> </extension><br /></pre><br /><br /><div style="text-align: justify;">The commandID opens the org.eclipse.ui.window.preferences with all the preferences. The parameter passed to the command tells the Preferences to open the preference window with the page that we want.<br /></div><br />Have fun !.KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-54960758854324945092009-02-18T19:14:00.000-08:002009-02-18T21:40:27.647-08:00Eclipse : How to Implement ISelectionProviderISelectionProvider interface provides a way to send selection events to the the ISelectionService which is received by all the ISelectionListener implementing views. All the JFace Structured viewers implements the ISelectionProvider and provide a StructuredSelection.<br /><br />There are scenarios where we have a custom view which might want to fire a Selectionto the listeners. Let us look at how to do that.<br /><br />Say you have a view with a Button and on clicking the button you want to send a selection event.<br /><br /><pre name="code" class="java"><br /><br />import org.eclipse.core.runtime.ListenerList;<br />import org.eclipse.jface.viewers.ISelection;<br />import org.eclipse.jface.viewers.ISelectionChangedListener;<br />import org.eclipse.jface.viewers.ISelectionProvider;<br />import org.eclipse.jface.viewers.SelectionChangedEvent;<br />import org.eclipse.jface.viewers.StructuredSelection;<br />import org.eclipse.swt.SWT;<br />import org.eclipse.swt.events.MouseAdapter;<br />import org.eclipse.swt.events.MouseEvent;<br />import org.eclipse.swt.layout.GridLayout;<br />import org.eclipse.swt.widgets.Button;<br />import org.eclipse.swt.widgets.Composite;<br />import org.eclipse.ui.part.ViewPart;<br /><br />public class ButtonView extends ViewPart implements ISelectionProvider {<br /><br /> private String selection;<br /><br /> ListenerList listeners = new ListenerList();<br /><br /> Button button = null;<br /><br /> @Override<br /> public void createPartControl(Composite parent) {<br /> parent.setLayout(new GridLayout(2, false));<br /> button = new Button(parent, SWT.BORDER);<br /> button.setText("Press Me");<br /> getSite().setSelectionProvider(this);<br /> button.addMouseListener(new MouseAdapter() {<br /> @Override<br /> public void mouseDown(MouseEvent e) {<br /> setSelection(new StructuredSelection(button.getText()));<br /> }<br /> });<br /> }<br /><br /> @Override<br /> public void setFocus() {<br /> }<br /><br /> public void addSelectionChangedListener(ISelectionChangedListener listener) {<br /> listeners.add(listener);<br /> }<br /><br /> public ISelection getSelection() {<br /> return new StructuredSelection(selection);<br /> }<br /><br /> public void removeSelectionChangedListener(<br /> ISelectionChangedListener listener) {<br /> listeners.remove(listener);<br /> }<br /><br /> public void setSelection(ISelection select) {<br /> <br /> Object[] list = listeners.getListeners();<br /> for (int i = 0; i < list.length; i++) {<br /> ((ISelectionChangedListener) list[i])<br /> .selectionChanged(new SelectionChangedEvent(this, select));<br /> }<br /> }<br /><br />}<br /><br /><br /></pre><br /><br />Now the ButtonView is implementing the ISelectionProvider and registered itself as a SelectionProvider to the workbench site. Now lets add the view to the views extension point. We will also create a ButtonListenerView which behaves as a SelectionListener by implementing ISelectionListener.<br /><br /><pre name="code" class="java"><br /><br />import org.eclipse.jface.viewers.ISelection;<br />import org.eclipse.jface.viewers.StructuredSelection;<br />import org.eclipse.swt.SWT;<br />import org.eclipse.swt.widgets.Button;<br />import org.eclipse.swt.widgets.Composite;<br />import org.eclipse.ui.ISelectionListener;<br />import org.eclipse.ui.IWorkbenchPart;<br />import org.eclipse.ui.part.ViewPart;<br /><br />public class ButtonListenerView extends ViewPart implements ISelectionListener {<br /><br /> Button button;<br /><br /> @Override<br /> public void createPartControl(Composite parent) {<br /> getSite().getPage().addSelectionListener(this);<br /> button = new Button(parent, SWT.BORDER);<br /> button.setText("Before Selection Happened");<br /> }<br /><br /> @Override<br /> public void setFocus() {<br /> <br /><br /> }<br /><br /> public void selectionChanged(IWorkbenchPart part, ISelection selection) {<br /> if (part instanceof ButtonView) {<br /> String text = ((StructuredSelection) selection).getFirstElement()<br /> .toString();<br /> button.setText(text);<br /> }<br /> }<br /><br />}<br /><br /></pre><br /><br /><br />Now ButtonView sends the selection event to the selection service and the ButtonListenerView listens for the Selection events from the workbench. There is one more step to add the views to the views extension.<br /><br /><pre name="code" class="xml"><br /> <extension<br /> point="org.eclipse.ui.views"><br /> <view<br /> class="com.blog.sample.ui.ButtonView"<br /> id="com.blog.sample.ui.ButtonView"<br /> name="Button View"<br /> restorable="true"><br /> </view><br /> <view<br /> class="com.blog.sample.ui.ButtonListenerView"<br /> id="com.blog.sample.ui.ButtonListenerView"<br /> name="Button Listener"<br /> restorable="true"><br /> </view><br /> </extension><br /><br /></pre><br /><br />Lets see the screenshot before and after the button is clicked on the ButtonView.<br /><br />Before the ButtonView send the ISelection,<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikEKS6YSA3Rzvnz5lKco5_uNvJl5eGnNH97EOticdUu9eJEQlofpAbrOc8YOh6T12-g7l73WzFFlJ53kOe5eWaWUAn33jSEXdvsLEszIzWxeKK6VcHfuZreuVOJBhTGdr7O7lXMrtTtzU/s1600-h/Screenshot.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 118px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikEKS6YSA3Rzvnz5lKco5_uNvJl5eGnNH97EOticdUu9eJEQlofpAbrOc8YOh6T12-g7l73WzFFlJ53kOe5eWaWUAn33jSEXdvsLEszIzWxeKK6VcHfuZreuVOJBhTGdr7O7lXMrtTtzU/s320/Screenshot.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5304367767202465890" /></a><br /><br />Now clicking the Press Me button sends a selection event to all the listeners. ButtonListenerView processes the selection in the selectionChanged method.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbZlvkEF7WNwKD-deAKCu41KaaGhD3k5YQltaUqd_ANjkgOMiooASvt-eraZI0QLcDxJcpDSlGHMYBlBVpsbsmzGYv-oVYda5n5uad29VTg33s-fOhpLh-odYXEvYWwsAscg3ZOClIpZc/s1600-h/Screenshot-1.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 120px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbZlvkEF7WNwKD-deAKCu41KaaGhD3k5YQltaUqd_ANjkgOMiooASvt-eraZI0QLcDxJcpDSlGHMYBlBVpsbsmzGYv-oVYda5n5uad29VTg33s-fOhpLh-odYXEvYWwsAscg3ZOClIpZc/s320/Screenshot-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5304368682695173426" /></a>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-86686216213159938692009-02-14T13:35:00.000-08:002009-02-18T21:40:27.647-08:00Eclipse : Keeping Preferences and Preferences UI separate<div style="text-align: justify;">Eclipse Preferences and PreferenceStore does not connect well with each other. When we have a Core plugin which handles the preferences and the initial values, keeping the UI in a separate plugin becomes difficult. The core plugin does not have access to the PreferenceStore since it is a not UI plugin. The UI Plugin with PreferencePage cannot populate using the Preferences from the core plugin.<br /></div><br /><div style="text-align: justify;">So how do we couple these together. The UI Plugin can create a PreferenceStore using the bundle id of the Core Plugin.<br /></div><br /><pre name="code" class="java"><br /><br />public class CorePreferencePage extends FieldEditorPreferencePage implements<br /> IWorkbenchPreferencePage {<br /><br />public CorePreferencePage() {<br /> IPreferenceStore store = new ScopedPreferenceStore(new InstanceScope(),<br /> ""com.blog.sample.core"");<br /> setPreferenceStore(store);<br />}<br /><br />@Override<br />protected void createFieldEditors() {<br /> BooleanFieldEditor formatOnSave = new BooleanFieldEditor("ABC", "ABC",<br /> getFieldEditorParent());<br /> addField(formatOnSave);<br /><br />}<br /><br />public void init(IWorkbench workbench) {<br /><br />}<br /><br />}<br /><br /></pre><br /><br /><div style="text-align: justify;">Now we can see the preferences of the Core Plugin in the UI Plugin's preference Page. But what if the preferences are not overridden and they are initialized from the Core Plugin using the Preference Initializer.<br /></div><br /><pre name="code" class="java"><br />public class CorePreferenceInitializer extends AbstractPreferenceInitializer {<br /><br />public CorePreferenceInitializer() {<br /><br />}<br /><br />@Override<br />public void initializeDefaultPreferences() {<br /> Preferences node = new DefaultScope().getNode("com.blog.sample.core");<br /> node.put("ABC", "true");<br />}<br />}<br /></pre><br /><br /><div style="text-align: justify;">and the core plugin declares an extension point to initialize the value when the preference node is accessed. But the initializer will be only invoked only if it is invoked from the bundle which is initialized.<br /></div><br /><pre name="code" class="xml"><br /><extension point="org.eclipse.core.runtime.preferences"><br /> <initializer class="com.blog.sample.core.CorePreferenceInitializer"><br /> </initializer><br /> </extension><br /></pre><br /><br /><div style="text-align: justify;">Now the initializer is invoked when it is accessed from the Core Plugin getPreferences. Now the UI Plugin does not know about the default values from the initializer. Whats the workaround?<br /></div><br />Add a duplicate extension point on the UI Plugin with the same initializer from the Core Plugin. Now when you open the prefernece page the initializer on the Core Plugin is invoked and the values are set to default.<br /><br />Have fun !KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com1tag:blogger.com,1999:blog-8961178336635312429.post-262201866482822082009-02-13T13:59:00.001-08:002009-02-18T21:40:27.647-08:00Eclipse : Adding a Static text to the toolbarThere are situations you need to show a static text on the toolbar with a user name or some sort of text. This can be done using the ControlContribution.<br /><br />JFace provides ControlContribution which can be added to the toolbar.<br /><br /><br /><pre name="code" class="java"><br /><br />public class LabelControlContribution extends ControlContribution<br />{<br /><br /> protected LabelControlContribution(String id)<br /> {<br /> super(id);<br /> }<br /><br /> @Override<br /> protected Control createControl(Composite parent)<br /> {<br /> final Label b = new Label(parent, SWT.LEFT);<br /> b.setText("Label: <Your User Name>");<br /> return b;<br /> }<br /><br />}<br /><br /></pre><br /><br />Add the ControlContribution to the coolbar in the ApplicationActionBarAdvisors fillCoolbar method.<br /><br /><pre name="code" class="java"><br />IToolBarManager toolbar1 = new ToolBarManager(SWT.FLAT<br /> | SWT.RIGHT_TO_LEFT);<br />coolBar.add(new ToolBarContributionItem(toolbar1, "label"));<br />toolbar1.add(new LabelContribution("Label"));<br /></pre><br /><br />Now the toolbar with the ControlContribution gets added to the Toolbar.KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-89313748284048031852009-02-13T13:17:00.001-08:002009-02-18T22:30:55.864-08:00Quick Tip : Multiple Target Platform support from 3.5M5Eclipse now supports adding multiple target platforms. The Target platform preference page in Plugin-Development allows adding multiple target platforms and assigning one of them as default.<br /><br />This feature is still experimental. More details at http://download.eclipse.org/eclipse/downloads/drops/S-3.5M5-200902021535/eclipse-news-M5.htmlKSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-81449461458707477882009-02-13T13:07:00.001-08:002009-02-18T21:40:27.648-08:00Quick Tip : Eclipse-BundleShape header - Package plugins as directoryEclipse MANIFEST.MF with a '.' for the Bundle-classpath packages the plugin as a jar file when the plugin is exported. But there are many cases where the plugin needs to be directory to read the files inside the plugin.<br /><br />From 3.5 , eclipse supports a new header in the MANIFEST.MF called Eclipse-BundleShape. The header allows two types 'dir' and 'jar'.KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-90436008223184520532009-02-11T22:14:00.001-08:002009-02-23T23:12:58.000-08:00Eclipse : How to create WizardsEclipse provides easy ways to create wizards and connect them to standard eclipse actions like New, Import,Export and so on. If you want to add a Wizard to file->New menu, you can use the newWizards extension point.<br /><br /><pre name="code" class="xml"><br /> <extension<br /> point="org.eclipse.ui.newWizards"><br /> <wizard<br /> class="com.blog.sample.loginapp.SampleWizard"<br /> id="com.blog.sample.loginApp.wizard3"<br /> name="Sample Wizard"><br /> </wizard><br /> </extension><br /></pre><br /><br />This adds a Sample Wizard to the File New action. Now the SampleWizard has to include all the pages in the wizard. First of all, the SampleWizard has to implement the IWizard interface ( can extend the abstract implementation Wizard ). <br /><br /><pre name="code" class="java"><br />import org.eclipse.jface.viewers.IStructuredSelection;<br />import org.eclipse.jface.wizard.Wizard;<br />import org.eclipse.ui.INewWizard;<br />import org.eclipse.ui.IWorkbench;<br /><br />public class SampleWizard extends Wizard implements INewWizard {<br /><br /> public SampleWizard() {<br /> <br /> }<br /><br /> @Override<br /> public boolean performFinish() {<br /> <br /> return false;<br /> }<br /><br /> public void init(IWorkbench workbench, IStructuredSelection selection) {<br /> <br /><br /> }<br /><br />}<br /></pre><br /><br />This creates a Wizard as shown below.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9sUlOJQFurpD4nfxRxbA-BJ7tdeNPT1KruAjRiXnxnI2jkA34uG6kyocN6Yl2UkvZY6mPmFdpTLH4yL8_YM5fEhMznaLchqaNANjjOotK6Qdv2VeOSxM5A9QpAcfFLFk87QZFJ88tGGXQ/s1600-h/Screenshot.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 382px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9sUlOJQFurpD4nfxRxbA-BJ7tdeNPT1KruAjRiXnxnI2jkA34uG6kyocN6Yl2UkvZY6mPmFdpTLH4yL8_YM5fEhMznaLchqaNANjjOotK6Qdv2VeOSxM5A9QpAcfFLFk87QZFJ88tGGXQ/s400/Screenshot.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5306250982328875106" /></a><br /><br />Now to add a Page to the SampleWizard , create a WizardPage and add it. <br /><br /><pre name="code" class="java"><br /> public class SamplePage extends WizardPage {<br /><br /> Text text = null;<br /><br /> public SamplePage() {<br /> super("SamplePage1");<br /> setTitle("Page1");<br /> setDescription("Page1 Description");<br /> }<br /><br /> public void createControl(Composite parent) {<br /> Composite comp = new Composite(parent, SWT.NONE);<br /> comp.setLayout(new GridLayout(2, false));<br /> Label label = new Label(comp, SWT.NONE);<br /> label.setText("Text ");<br /> text = new Text(comp, SWT.BORDER);<br /> text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));<br /> setControl(parent);<br /> }<br /><br /> @Override<br /> public boolean isPageComplete() {<br /> return super.isPageComplete();<br /> }<br /><br /> }<br /></pre><br /><br />Now the SamplePage has to be added to the SampleWizard via the addPages method as follows.<br /><br /><pre name="code" class="java"><br /> @Override<br /> public void addPages() {<br /> super.addPages();<br /> addPage(samplePage);<br /> }<br /></pre><br /><br />This adds the page as below.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_22_lrHkPWOE/SaObcgiITrI/AAAAAAAADkI/JbH5LBErOJE/s1600-h/Screenshot-1.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 382px;" src="http://4.bp.blogspot.com/_22_lrHkPWOE/SaObcgiITrI/AAAAAAAADkI/JbH5LBErOJE/s400/Screenshot-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5306255700044304050" /></a><br /><br />The isPageComplete() method from the SamplePage enables/disables the Next button if the page is complete. Once all the data is taken from the page. The isPageComplete returns true to the SampleWizard. At the end, the SampleWizard enables the finish the Button by looking at the canFinish return value. The canFinish can return true if the mandatory values are entered.<br /><br />Have fun !.KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-4793966890506768562009-02-11T14:57:00.001-08:002009-02-18T21:40:27.648-08:00Eclipse : How to save a dirty viewEclipse has editors and views. When the contents of a editor is modified, the editor's state changes to dirty state and the user is asked to save it when he closes the application.<br /><br />Editors implement IEditorPart interface which extends ISaveablePart. ISaveablePart has the following methods.<br /><br /><pre name="code" class="java"><br /><br /> @Override<br /> public void doSave(IProgressMonitor monitor)<br /> {<br /><br /> }<br /><br /> @Override<br /> public void doSaveAs()<br /> {<br /><br /> }<br /><br /> @Override<br /> public boolean isDirty()<br /> {<br /><br /> return false;<br /> }<br /><br /> @Override<br /> public boolean isSaveAsAllowed()<br /> {<br /><br /> return false;<br /> }<br /><br /> @Override<br /> public boolean isSaveOnCloseNeeded()<br /> {<br /><br /> return false;<br /> }<br /><br /></pre><br /><br />So if you need the ViewPart to behave like a editor when the content is modified, the ISaveablePart should be implemented by the ViewPart class.<br /><br />More importantly when something is changed on the View, set the dirty flag to true and fire a property change event to the workbench, otherwise the Save menu item will not be enabled on the workbench.<br /><br /><pre name="code" class="java"><br /> public boolean isDirty()<br /> {<br /> return _dirty;<br /> }<br /><br /> protected void setDirty(boolean value)<br /> {<br /> _dirty = value;<br /> firePropertyChange(PROP_DIRTY);<br /> }<br /></pre>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-19348112586337873792009-02-11T13:17:00.001-08:002009-02-18T21:40:27.648-08:00Eclipse : Most useful Eclipse plugins for a developerThere are lot of open source and commercial eclipse plugin available out there. Here are some of the best plugins that i have used during my eclipse based application development.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Subclipse</span></span><br /><br />Checking out code from the version control will be the first step for any developer. CVS, Subversion are two of the mostly used Version control systems. Eclipse IDE provides the CVS Repository access by default. Since we had a Subversion repository for our version control, we needed a Subversion client for eclipse. There are two major SVN Clients for eclispe, Subclipse and Subversive.<br /><br />We have chosen Subclipse over subversice since we had some performance problem using Subversive.<br /><br />You can get it from <a href="http://subclipse.tigris.org/">http://subclipse.tigris.org/</a><br /><br /><span style="font-weight: bold;font-size:130%;" >Checkstyle</span><br /><br />Software development involves the teams writing code properly by following some coding standard. Following the coding standard helps in many ways like, maintainability and readability. Eclipse has plugins which enforces these coding standards during the development. Checkstyle plugin is a freely available plugin which checks coding standards and also some java best practices.<br /><br />Checkstyle is configurable through the Eclipse preferences where the user can import a predefined checkstyle xml file.<br /><br />You can get it from <a href="http://eclipse-cs.sourceforge.net/">http://eclipse-cs.sourceforge.net/</a><br /><br /><span style="font-weight: bold;font-size:130%;" >Code Coverage</span><br /><br />Softwares need to be tested at different levels like unit testing, system testing , integration testing and so on. The software programmer usually writes unit test code to test an unit of functionality in the software. The unit tests cover a particular portion of the code base developed. The code coverage tools highlights the unit test covered code and gives statistical information about the testing.<br /><br />Eclipse has a plugin called EclEmma which integrates into the Run Configuration and gives all the coverage details.<br /><br />you can get it from <a href="http://www.eclemma.org/">http://www.eclemma.org/</a><br /><br /><br /><span style="font-weight: bold;font-size:130%;" >DBViewer</span><br /><br />Most projects has a backend database which holds the application data. The developers writes SQL queries to retrieve the database results or maps the database columns to Object relational mapping tools like Hibernate. DBViewer plugin helps doing all this inside eclipse ide itself rather than using additional java sql tools.<br /><br />You can configure any number of databases and query them and edit them using a simple table from inside eclipse.<br /><br />You can get if from <a href="http://www.ne.jp/asahi/zigen/home/plugin/dbviewer/about_jp.html">http://www.ne.jp/asahi/zigen/home/plugin/dbviewer/about_jp.html</a><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Plugin Builder</span></span><br /><br />Once the plugins are developed in eclipse. The plugins and features needs to be built on a build machine to achieve continuous integration. Pluginbuilder is a eclipse plugin which helps creating build xml files from inside eclipse.<br /><br />You can get it from <a href="http://www.pluginbuilder.org/">http://www.pluginbuilder.org/</a>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com2tag:blogger.com,1999:blog-8961178336635312429.post-6756779196962710502009-02-11T12:27:00.001-08:002009-02-18T21:40:27.648-08:00Eclipse : Uncloseable ViewPartThere are some cases where view part must not be closed in a perpective. Eclipse RCP provides an easy way to make the viewpart uncloseable.<br /><br />From the perspective class which defines the layout for the Perspective, the viewpart can be set uncloseable.<br /><br /><br /><pre name="code" class="java"><br /> public void createInitialLayout(final IPageLayout layout)<br /> {<br /> final String editorArea = layout.getEditorArea();<br /> layout.addView(View.ID, IPageLayout.LEFT, 0.5f, editorArea);<br /> layout.getViewLayout(View.ID).setCloseable(false);<br /> }<br /></pre>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-50813164606164309682009-02-02T11:35:00.001-08:002009-02-18T21:40:27.648-08:00Eclipse RCP: Removing unwanted actionSets from menubar<span style="font-size:100%;"><span style="font-family:arial;">Eclipse</span> </span><span style="font-size:100%;">provides some default actionSets when you include the plugins like org.eclipse.ui. In many cases, the application does not need these actions. </span><div class="Section1" style="font-family:arial;"><div style="text-align: justify;">So how do we remove these actions from the menubar and toolbar? Well, there is <span style="font-size:100%;">this ugly code which removes the unwanted action sets.</span><br /></div><br /><pre name="code" class="java"><br />final ActionSetRegistry reg = WorkbenchPlugin.getDefault().getActionSetRegistry();<br />final IActionSetDescriptor[] actionSets = reg.getActionSets();<br />final String[] removeActionSets = new String[] {<br />"org.eclipse.search.searchActionSet","org.eclipse.ui.cheatsheets.actionSet",<br />"org.eclipse.ui.actionSet.keyBindings","org.eclipse.ui.edit.text.actionSet.navigation",<br />"org.eclipse.ui.edit.text.actionSet.annotationNavigation","org.eclipse.ui.edit.text.actionSet.convertLineDelimitersTo",<br />"org.eclipse.ui.edit.text.actionSet.openExternalFile","org.eclipse.ui.externaltools.ExternalToolsSet",<br />"org.eclipse.ui.WorkingSetActionSet","org.eclipse.update.ui.softwareUpdates",<br />"org.eclipse.ui.actionSet.openFiles","org.eclipse.mylyn.tasks.ui.navigation", };<br /><br />for (int i = 0; i < actionSets.length; i++) {<br />boolean found = false;<br />for (int j = 0; j <; removeActionSets.length; j++) { if(removeActionSets[j].equals(actionSets[i].getId())) { found= true; } } if(!found) { continue; } final IExtension ext = actionSets[i].getConfigurationElement().getDeclaringExtension(); reg.removeExtension(ext, new Object[] { actionSets[i] }); } </pre><br /><div style="text-align: justify;"><span style="line-height: 115%;font-size:100%;" >But this code needs to access restricted API from eclipse </span><span style="line-height: 115%;font-size:100%;" >internal packages. When the eclipse activities are introduced the above</span> <span style="line-height: 115%;font-size:100%;" >discouraged can be declaratively done inside the plugin.xml file. If you wanted</span> <span style="line-height: 115%;font-size:100%;" >to remove the search menu from the menubar, define an activity and use the pattern org.eclipse.search.* as the activity pattern as below. </span><br /></div><p class="MsoNormal"><span style="line-height: 115%;font-size:100%;" ><br /><br /><pre name="code" class="xml"><br /><extension point="org.eclipse.ui.activities"><br /><activity id="com.sequenom.ivd.actitivities.unwantedActionSet1" name="Unwanted Search ActionSet"><br /> <enabledwhen><br /> <with variable="activePartId"> <br /><equals value="com.sequenom.ivd.actitivities.unwantedActionSet"> <br /></equals> <br /></with></enabledwhen></activity></extension><br /><br /><activitypatternbinding activityid="com.sequenom.ivd.actitivities.unwantedActionSet1" pattern="org.eclipse.search.*"><br /></activitypatternbinding><br /></pre><br />This will remove the search menu from your application. Have fun !</span></p></div>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com3tag:blogger.com,1999:blog-8961178336635312429.post-57093497889899414362009-01-21T13:25:00.001-08:002009-02-18T21:40:27.648-08:00Eclipse RCP : Sorting JFace Viewer contentsThe JFace viewer contents can be sorted by assigning them a ViewerSorter.<br /><br /><pre name="code" class="java"><br />viewer.setSorter(new MyViewerSorter());<br /><br />public class MyViewerSorter extends ViewerSorter<br />{<br />@Override<br /> public int compare(Viewer viewer, Object o1, Object o2)<br /> {<br /> return o1.toString().compareToIgnoreCase(o2.toString());<br /> }<br />}<br /></pre><br /><br />This will sort the elements in alphabetical order.KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-17899106493676015062009-01-20T22:18:00.001-08:002009-02-18T21:40:27.648-08:00Eclipse RCP: Command, Handler enabledWhen with a particular selection object<span style="font-weight: bold;">Command Framework</span><br /><div style="text-align: justify;">Command framework allows to add menubar and toolbar actions via handlers. To create a command in the application.<br /></div><br />Create an extension of the commands<br /><pre name="code" class="xml"><br /><br /><extension point="org.eclipse.ui.commands"><br /><command defaulthandler="com.mycomp.app1.commands.SampleHandler" id="com.mycomp.app1.commands..SampleCommand" name="Add User"><br /></command><br /></extension><br /></pre><br /><div style="text-align: justify;">Implement the SampleHandler which is the default handler for the command. The handler should implement the interface IHandler or can simply extend AbstractHandler. Now we can add the Command to application main menubar, toolbar or to a menubar and toolbar of a view.<br /></div><br />To add it a to a view's toolbar<br /><br /><pre name="code" class="xml"><br /><extension point="org.eclipse.ui.menus"><br /><menucontribution locationuri="toolbar:com.mycomp.app1.SampleView"><br /><command commandid="com.mycomp.app1.commands.SampleCommand" icon="icons/sample.png" label="Sample" style=""><br /></command><br /></menucontribution><br /></extension><br /></pre><br /><div style="text-align: justify;">This will add the ha<span style="font-family: arial;">ndler to the SampleView's toolbar. But to activate this, we need to have activeWhen command expression.</span><br /></div><br /><pre name="code" class="xml"><br /><activeWhen><br /> <equals variable="activePartId"><br /> <value="com.mycomp.app1.SampleView"/><br /> </with><br /></activeWhen><br /></pre><br /><br />Now the SampleHandler will be on the toolbar of the view. The handler execute method can get the activepart,selection, and different workbench values from HandlerUtil class.<br /><br />HandlerUtil.getActiveWorkbenchWindow(event) or HandlerUtil.getCurrentSelection(event).<br /><br /><div style="text-align: justify;">To enable and disable the action based on selection, enabledWhen needs to be extended, Now lets enable the action only for one selection.<br /></div><br /><pre name="code" class="xml"><br /><enabledWhen><br /><with variable="selection"><br /><value="1"><br /></count><br /></with><br /></enabledWhen><br /></pre>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-88593088161946779562009-01-18T18:09:00.001-08:002009-02-18T21:40:27.649-08:00Eclipse RAP: Creatiing a multiuser RAP Application<span style="font-weight: bold;">What is RAP ?</span><br /><br /><div style="text-align: justify;">Rich Ajax Platform, a web development platform for RCP Developers. RAP uses the whole plugin architecture of the eclipse platform and provides a SWT port called RWT for the web browsers. RWT uses the qooxdoo java script library to create the User interfaces on the browser side.<br /><br /><span style="font-weight: bold;">Singleton</span><br /><br />Singleton pattern is something which is widely used on the eclipse platform. But for a web based application where multiple users will be accessing the application we need session based singleton implementation.<br /><br /><span style="font-weight: bold;">SessionSingletonBase</span><br /><br />Eclipse RAP provides a base class called SessionSingletonBase which provides a singleton implementation for each session and avoids the sharing the application state between the users.<br /><br />so just extends the SessionSingletonBase and create a singleton instance as done below.<br /><br /><pre name="code" class="java"><br />SampleAppPlatform extends SessionSingletonBase {<br /><br /> public static final SampleAppPlatform getInstance() {<br /> return (SampleAppPlatform) getInstance(SampleAppPlatform.class);<br /> }<br />}<br /></pre><br /><br />and try accessing the RAP web application from multiple browser instances and check the SampleAppPlatform state. It will be different.<br /><br /><br /><br /></div>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0tag:blogger.com,1999:blog-8961178336635312429.post-36442068636079219792009-01-16T13:20:00.001-08:002009-02-18T21:40:27.649-08:00Eclipse: Build Product, Coverage and lot of Reports.<div style="text-align: justify;"><span style="font-weight: bold;">Continous Integration</span><br /><br />Continuous integration is a practive where developers integrate their work frequently. This help the team increase their productivity by detecting the integrating errors as early as possible during the development. There are a lot of build tools which helps in automating the build process with different reports which helps the developers to increase their work productivity.<br /><br /><span style="font-weight: bold;">Ant, Maven</span><br /><br />Ant and Maven are two build tools which are very widely used in the java build process. Though ANT is a old and little complicated tool than the Maven, it gives the flexibility to do the build for any kind of software application.<br />Maven works great for almost all kinds of java application like web application, desktop applications. Maven also generates a whole lot of reports which helps the team at various levels to see the progress of the development.<br /><br /><span style="font-weight: bold;">Building Eclipse Products</span><br /><br />Building eclipse product is always a difficult job if you want to do it outside the Eclipse Environment. And especially building eclipse product with maven not so easy work. Though there are existing plugins which does the product build little easier, they are not as efficient as the ANT counter part.<br /><br />Since eclipse requires its own run time environment for building and running, the Maven structure does not help a lot. The following maven plugins does help in building eclipse plugins<br /><br /><ul><li><a href="http://www.eclipse.org/articles/article.php?file=Article-Eclipse-and-Maven2/index.html">maven-psteclipse-plugin</a>.<br /></li><li><a href="http://mojo.codehaus.org/pde-maven-plugin/">maven-pde-plugin</a>.</li></ul>But running the test cases and generating different reports based on this is a difficult process using the above tools.<br /><br /><span style="font-weight: bold;">Combining ANT and Maven</span><br /><br /><div style="text-align: justify;">PluginBuilder is a eclipse plugin which provides an easy mechanism to create the ANT build scripts for building eclipse plugins, running test cases, and building the product. And it works out of the box.<br /></div><br />Download it from http://www.pluginbuilder.org/<br /><br />Create your plugin project with the test cases in a separate fragment project.<br /><br /><div style="text-align: justify;">Create the build.xml and other supporting files for the ANT Build which creates Product, Test Report and Test Coverage Report.<br /></div><br /><div style="text-align: justify;">Configure a ANT build step on the Automated build tool such as Luntbuild.<br /></div><br /><div style="text-align: justify;">Now for the usual Maven reports and site generation we can use the Maven PDE plugin without the test option. This should not include the test fragments in build path.<br /></div><br /><div style="text-align: justify;">This is it. You get a Product file, Unit Test Reports, Unit Test Coverage and all maven reports deployed as a site.<br /></div><br /><div style="text-align: justify;">This tutorial doesnt give you step by step procedure but if you need help doing anything above. Just drop in a comment.<br /></div><br /></div>KSGhttp://www.blogger.com/profile/03901914986996167494noreply@blogger.com0