tag:blogger.com,1999:blog-33215146299340174932024-02-21T01:55:26.030+01:00Swinging the bottleBlog about J2EE - Ease of development and productivitys2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-3321514629934017493.post-41696343533889889022016-06-26T12:09:00.001+02:002016-07-11T11:55:56.782+02:00Selenium vs Selenium (with Open Source Stack)<div style="font-family: Arial;">
<div style="font-family: arial;">
In the past I did a comparative Selenium vs Sahi vs HP QTP, finally our decision was to use Selenium because of its <a href="http://www.seleniumhq.org/ecosystem/">ecosystem</a> and the possibility to execute the test with Java, this final point was one the keys of the success of the project as we could use some Java libraries to extend the testing functionalities and have integrated testing against WS, images comparative, pdf comparative...</div>
<div style="font-family: arial;">
<br /></div>
<span style="font-family: "arial";">This time, I'm in a new company, new project, and now we have a dilemma to use Ranorex or Selenium. Ranorex is a powerful tool that I like, but the question is if is it worthwhile using Selenium with a stack of open source tools instead of Ranorex. And after some proofs of concept over our application, we arrive to the conclusion that it is not worth it to pay for licences. But anyway, if we consider the amount necessary to buy licences irrelevant, </span><b style="font-family: arial;">which solution is better for us?</b><br />
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
There are a lot of articles comparing automation testing tools, most of them talk about Selenium:</div>
<ul style="font-family: arial;">
<li><a href="http://www.ranorex.com/ranorex-vs-selenium.html">Ranorex vs. Selenium </a></li>
<li><a href="http://sahipro.com/sahi-vs-selenium/">Sahi vs. Selenium</a>: </li>
<li><a href="http://www.gallop.net/blog/tag/test-automation-tools-comparison/">Accelerate your Test lifecycle with these Automation tools</a></li>
<li><a href="http://www.topicmatch.net/?p=46">Which automation testing tools are better?</a></li>
<li><a href="http://qafacetime.blogspot.com.es/2014/05/qafacetime.html">QTP vs TestComplete vs Selenium</a></li>
<li><a href="http://www.logigear.com/magazine/automation-test/test-automation-tool-shopping-guide/">Test automation tool shopping guide</a></li>
<li><a href="http://www.testnbug.com/2015/02/automation-war-unified-functional-testingqtp-vs-selenium/">Automation War – Unified functional Testing(QTP) Vs Selenium </a></li>
<li><a href="http://www.dotnetcurry.com/tools/1004/comparing-automated-testing-tools-codedui-qtp-selenium">Comparison of Automated Testing Tools: Coded UI Test, Selenium and QTP</a> </li>
</ul>
<div style="font-family: arial;">
For some of them, it is easy to see that are totally partial as they were written by the private companies that Selenium is compared against. But, <b>are those arguments true?</b> Because I don't see too many comments against those comparatives.</div>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
From my point of view all<b> </b>that they say <b>is true</b>, at least at the time the articles were written, <b>but with a trick</b>, and It is that no one says that there are a lot of frameworks/tools ready to use that at least give us the same power (if not more) as the vendors tools give. With this in mind, today, you don't need to build a framework from scratch that can help you in the testing with Selenium, these days the mission of the developer is to choose the correct open source stack of tools for his/her needs.</div>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
So in the next lines I will show you a proof of concept between Ranorex and a stack of open source tools with Selenium.</div>
<div style="font-family: arial;">
<br /></div>
<h2 style="font-family: arial;">
POC: Selenium (with open source stack) vs Ranorex</h2>
<div style="font-family: arial;">
Use cases:</div>
<ul style="font-family: arial;">
<li>Focused on browser testing.</li>
<li>Build the same test with Ranorex and Selenium.</li>
<li>Test the same grid in two different pages.</li>
</ul>
<div style="font-family: arial;">
Challenges:</div>
<ul style="font-family: arial;">
<li>The rapid implementation of new tests by not high skilled developers.</li>
<li>Maintainability of the code.</li>
<li>Integration with existing solutions at the company: TFS / HPALM.</li>
<li>Integration with the rest of the tools of the project (AUT).</li>
</ul>
<h3 style="font-family: arial;">
Selenium stack - Solution description</h3>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
With Selenium you can choose to implement the solution in a wide range of languages, for this time we choose to use Java because the architecture in the AUT is implemented in Java, so in this case the solution will be<span style="color: #6aa84f;"> </span><span style="color: #38761d;">closer to the experience of the developers</span>.</div>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
<b>Stack of tools</b>: Cucumber + Serenity + Selenium + IntelliJ IDEA</div>
<div style="font-family: arial;">
<br /></div>
<div class="separator" style="clear: both; font-family: arial; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL-6pgNsAr4ib-RmzTOFYDaqw6Vv2ueLQG9FDWCOFEMreuRMa0G6ZbEkptDxmZo1dIV-DEU70PCNWqJ6k-WsoN7HsO4tiofeXd4mrKdf-A2lYqS3n4Zvg-jFpGR71Oz_xNVd-7kSu-3jkC/s1600/serenity.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="37" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL-6pgNsAr4ib-RmzTOFYDaqw6Vv2ueLQG9FDWCOFEMreuRMa0G6ZbEkptDxmZo1dIV-DEU70PCNWqJ6k-WsoN7HsO4tiofeXd4mrKdf-A2lYqS3n4Zvg-jFpGR71Oz_xNVd-7kSu-3jkC/s320/serenity.png" width="320" /></a></div>
<ul style="font-family: arial;">
<li><a href="https://cucumber.io/">Cucumber</a> is a framework for writing and executing high level descriptions of the functionality of the software.</li>
<li><a href="http://www.thucydides.info/">Serenity</a> is an Open Source library for writing better quality automated acceptance tests faster. The final decision to choose Serenity was by the DI (dependency injection) already configured by the framework that ease the decoupling of the components. Another framework also highly considered was <a href="http://selenide.org/">Selenide</a>.</li>
<li><a href="http://www.seleniumhq.org/">Selenium</a> is a portable software testing framework for web applications. It provides commands for performing actions in a browser.</li>
<li><a href="https://www.jetbrains.com/idea/">IntelliJ IDEA </a>is a Java integrated development environment (IDE).</li>
</ul>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
---------------------------------------------------</div>
<div style="font-family: arial;">
Off the record:</div>
<div style="font-family: arial;">
In C# there are also frameworks that can help in the development with a lot of functionalities, for example, this could be the stack of tools:</div>
<ul style="font-family: arial;">
<li><a href="http://www.specflow.org/">Specflow</a>: is a framework for writing and executing high level descriptions of software's functionality.</li>
<li><a href="https://github.com/ObjectivityBSS/Test.Automation">ObjectivityBSS</a> / <a href="http://seleno.teststack.net/">Seleno</a>...</li>
<li><a href="http://www.seleniumhq.org/">Selenium</a> is a portable software testing framework for web applications. It provides commands for performing actions in a browser.</li>
<li><a href="https://www.visualstudio.com/">Visual Studio</a>: is a C# integrated development environment (IDE).</li>
</ul>
<div style="font-family: arial;">
---------------------------------------------------</div>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
The designed solution is based on BDD and the Pattern, well-proven by being widely adopted in UI testing, “Page Object”.</div>
<div class="separator" style="clear: both; font-family: arial; text-align: center;">
</div>
<div style="font-family: arial;">
<br /></div>
<div class="separator" style="clear: both; font-family: arial; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqDyHWYNoFuATa5JLhJumF1EaQCJdI0Eg5CC-hKGO0K2ZrqNxgb8fXSGx3sU39_SlSCxQih_APNBwh-FsAVdWR6nS-ae8bvo4dloaILFLdrqU0P6KVKtqXjOOornXHpYUsCYXZX4VLvk5r/s1600/pageObject.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqDyHWYNoFuATa5JLhJumF1EaQCJdI0Eg5CC-hKGO0K2ZrqNxgb8fXSGx3sU39_SlSCxQih_APNBwh-FsAVdWR6nS-ae8bvo4dloaILFLdrqU0P6KVKtqXjOOornXHpYUsCYXZX4VLvk5r/s400/pageObject.png" width="400" /></a></div>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
The integration between layers is made by DI.</div>
<div style="font-family: arial;">
<br /></div>
<h3 style="font-family: arial;">
Ranorex - Solution description</h3>
<div style="font-family: arial;">
<b><br /></b> <b>Stack of tools</b>: Ranorex and Visual Studio.</div>
<ul style="font-family: arial;">
<li>Ranorex Studio: tools for creating automated testing projects to test any desktop, web or mobile application.</li>
<li>Visual Studio: is a C# integrated development environment (IDE).</li>
</ul>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
The main design idea: export Ranorex project to Visual Studio to use Ranorex as a library in the VS project to the interaction with the Browser.</div>
<div style="font-family: arial;">
<br /></div>
<div class="separator" style="clear: both; font-family: arial; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOzDTBQnwAjRsJYy8TV3NU3Nq6lbROvxWIxhyphenhyphenvqHyi3q0DJ83uyoBtqF4ti89ulVowXV_s9u7driH2vZxXHNW9mXIEGhvhvJb5zOguOAIQNuUofO1LlYJPFsb5H0zT9nuFTztanfMfesbJ/s1600/vs%252Branorex.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="66" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOzDTBQnwAjRsJYy8TV3NU3Nq6lbROvxWIxhyphenhyphenvqHyi3q0DJ83uyoBtqF4ti89ulVowXV_s9u7driH2vZxXHNW9mXIEGhvhvJb5zOguOAIQNuUofO1LlYJPFsb5H0zT9nuFTztanfMfesbJ/s320/vs%252Branorex.png" width="320" /></a></div>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
The reason for using this kind of design is because the AUT is very old, plenty of iframes, duplicated id's (don't ask me please!), and so on; in a way that there are places where the only possibility to identify an element of the page is by its shown text. The idea is to use the in18 properties files from the UAT (key/value) -> in the VS project load the correct value from a given in18 key and passes it as a parameter to the Ranorex library.</div>
<div style="font-family: arial;">
<br /></div>
<ul style="font-family: arial;">
<li>In Visual Studio project structure we will follow the same name convention and structure as we did for the Selenium part </li>
<li>The page components are stored in the Ranorex library.</li>
</ul>
<div>
<h3 style="font-family: arial;">
Comparative</h3>
<div class="separator" style="clear: both; font-family: arial; text-align: center;">
</div>
<div class="separator" style="clear: both; font-family: arial; text-align: center;">
</div>
<div class="separator" style="clear: both; font-family: arial; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCYaOsUpZ9xuKM5JVXrs8J9kaSXhK26G23asR5nbXlLRXJjc8M9RwyG6K7v23ifSwavidOlva2YmjWcLagMV9fw5hKxRrmRk5gIeVW-wmVBIkDlOweWHdxZp1EKqsEpq6wrYesGHfv5OAJ/s1600/comparative.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCYaOsUpZ9xuKM5JVXrs8J9kaSXhK26G23asR5nbXlLRXJjc8M9RwyG6K7v23ifSwavidOlva2YmjWcLagMV9fw5hKxRrmRk5gIeVW-wmVBIkDlOweWHdxZp1EKqsEpq6wrYesGHfv5OAJ/s320/comparative.png" width="320" /></a></div>
<div style="font-family: arial;">
<br /></div>
<ul>
<li style="font-family: arial;"><b>Support desktop applications</b>: Selenium is based on the implementation of a WebDriver. Although there’s also an implementation to test WinForms and WPF and in this comparative we are talking about browsers.</li>
<li><b style="font-family: arial;">Learning curve</b><span style="font-family: "arial";">: for the punctuation this example was taken into account: the effort of an intern to automatize, from scratch, a page with a search form (with 5 fields) and a result list (only following the documentation). This is a very interesting point, because the people at first glance can think that Ranorex maybe is easier because of its WYSIWYG style, but in the proof, the interns (without previous knowledge) said that they prefer the Selenium solution. Maybe this was because of the problems to get a good identifier directly through Ranorex that all the recorded things had to be re-written. Someone can say that those problems where because of the lack of knowledge, well, this is something to take into account in the "Learning curve" item. Another possible criticism of Selenium is that you need to do manual programming, but the fact is that once you have a template, the skill of the programmer needed is very low.</span></li>
<li><b style="font-family: arial;">Maintainability & Reusability</b><span style="font-family: "arial";">: in both solutions we have the components decoupled of from the test, so the implementation of the tests in both solutions are very similar. Maybe the people that like Ranorex can say that it is better and the people of Selenium can say the same. I think that it is very difficult to say which one is better. </span></li>
<li><b style="font-family: arial;">Results stability (retry capabilities)</b><span style="font-family: "arial";">: stability of results against false positive. With Selenium you have more control over the execution flow and the politics of retries can be configured before giving an error as a result in the Serenity framework.</span></li>
<li><b style="font-family: arial;">Multi-language testing (i18n support)</b><span style="font-family: "arial";">: the implementation is based on getting the multilanguage properties as (locale strings:key/value) from the AUT and then use the value of the current language as a parameter in the test. In fact, this locale file can be loaded at 'runtime' from the AUT. This can be done by both solutions, but with Ranorex the cost of maintenance is higher.</span></li>
<li style="font-family: arial;"><b>Integration with other type of tests</b>: the integration with other tools in the execution of a Test Case. As the design of the solution in Ranorex is with VS, it gives all the power of C#.</li>
<li style="font-family: arial;"><b>Integration with HPALM</b>: the result of the execution can update the test cases at HPALM</li>
<li style="font-family: arial;"><b>Parallelization of the executions</b>: the test can be executed in the same machine in parallel and against different servers. This is a key point in terms of resources,<span style="color: #cc0000;"> add VMs</span> for parallelization means more maintenance of servers and more cost in terms of hardware and licences.</li>
<li style="font-family: arial;"><b>Multiplatform</b> (Windows, Linux, “headless browser”): with “<b><span style="color: #38761d;">headless browser</span></b>” and with Linux, it’s possible to execute the test in a <span style="color: #38761d;"><b>Docker container</b></span> maybe by the developer of the AUT (before a commit). This is another key point as it gives the possibility of the execution in the developer's machine, while the developer can do other tasks, This can be done also with VMs, but at the cost of more resources needed for the developers' machines.</li>
<li style="font-family: arial;"><b>Alignment with the company</b>: use of this tool in the rest of the company projects to share knowledge. Until now, Selenium is not used, but as the intern reflects, once the structure of the framework is established, then its use is easy.</li>
<li style="font-family: arial;"><b>Alignment with the AUT</b>: use of this solution in the AUT. The application is multiplatform with developer environment in Java, using Cucumber + Serenity + DBUnit + IntelliJ IDEA for testing the upgrade of the DB of the AUT.</li>
</ul>
<h3 style="font-family: arial;">
Conclusions - The "Vision"</h3>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
I don't want to get in into any kind of debate that "it seems" that this solution is better in someway and "bla bla bla", in something that can not be easily proved. If we are not talking about money, for me both solutions can give you very similar results, but there are some points to which no one can disagree (I hope!) and it is the parallelization and multiplatform execution. In the context of our AUT the parallelization is a key, the application is too big and the parallelization of the executions must be taken into account from the first steps.</div>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
Also, I don't want to say that this comparative can be applied to any project, for sure there are projects that the best approach is to use Ranorex (or some other tools like this), but <b><span style="color: #38761d;">in the context of this AUT</span></b> the best choice is without doubts <b><span style="color: #38761d;">the stack of Selenium tools</span></b>.</div>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
<b>The "Vision":</b></div>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
Nowadays we are facing to some kind of revolution in the IT world: microservices, nosql, react, docker containers...</div>
<div style="font-family: arial;">
<br /></div>
<div style="font-family: arial;">
In terms of functional testing I think that the future is that the developers can not only execute the unit test before any commit to the SCM, but also execute the integration tests and UI test; and the easier way to achieve this last point is with the execution of the UI test in a docker container or with a headless browser. And this only can be done with Selenium.</div>
</div>
<div style="font-family: arial;">
</div>
</div>
s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-813736605870990252016-03-03T09:39:00.000+01:002017-02-06T22:51:50.642+01:00Approaching to needs for an Automated Test Platform<br />
By Automated Test Platform we mean the infrastructure, tools, applications and software that can be used to include the automated test (usually functional test) in the pipeline of the <a href="https://en.wikipedia.org/wiki/Continuous_delivery" target="_blank">Continuous Delivery</a> (CD).<br />
<br />
There are different ways to set up an Automated Test Platform, we can find products like <a href="http://www.extensivetesting.org/" target="_blank">ExtensiveTesting</a>, <a href="http://atestingp.sourceforge.net/" target="_blank">Atestingp</a>, <a href="https://smartbear.com/" target="_blank">Smartbear</a>, ... on the other hand, you can build your customed platform integrating <a href="https://en.wikipedia.org/wiki/Test_management_tools" target="_blank">test management tools</a> in your Continuous Integration (CI) process.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjGZXSpZ9II0KmV3_zshyzMjRJG_aYCbllNx7_ODPCHZjt43WvA1HMirZA-OvfVS7jqEhqK4LbkPMeLHyl8LOSkK1UVzxS38_tt5ThHdmjTooyNEmdmn4YoKkOs8diEvRNjdvIkPFLMgZ0/s1600/all.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="182" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjGZXSpZ9II0KmV3_zshyzMjRJG_aYCbllNx7_ODPCHZjt43WvA1HMirZA-OvfVS7jqEhqK4LbkPMeLHyl8LOSkK1UVzxS38_tt5ThHdmjTooyNEmdmn4YoKkOs8diEvRNjdvIkPFLMgZ0/s320/all.png" width="320" /></a></div>
<br />
<br />
The aim of this article is not to compare different products, it is just to do a <i>simplified</i> exercise based on the checklist that an Automated Test Platform "must" have, i.e. a list of features you would think about, when you are searching for a solution.
<br/><br/>
<h3>From the users point of view</h3>
You must integrate different actors. The tools to be used have to be adaptable for the different kind of users.<br />
<ul>
<li>QA: management of use cases, test cases, test plans...</li>
</ul>
<ul>
<li>Developers/testers: test cases implementation.</li>
</ul>
<ul>
<li>DevOps: integration with the CD pipeline.</li>
</ul>
<ul>
<li>Managers: reports, reports... and more reports.</li>
</ul>
<br />
<h3>From the testers point of view</h3>
First of all, tests have to be <a href="https://en.wikipedia.org/wiki/Robustness_(computer_science)" target="_blank">Robust</a> and <a href="https://en.wikipedia.org/wiki/Stability_Model" target="_blank">Stable</a>. But also the tests implementation has to have:<br />
<ul>
<li>An easy learning curve for new developers.</li>
</ul>
<ul>
<li>Ease of development.</li>
</ul>
<ul>
<li>Easy of maintenance: be sure there will be changes, be ready for changes. </li>
</ul>
<ul>
<li>Portable: tests have to be executed in an easy way, when developing, as the same way as it will be executed automatically by the automated platform. </li>
</ul>
<br />
<h3>From the execution point of view</h3>
Here we are thinking about the ability to execute the test with different configurations and easy integration with deployment tools and continuous integration.<br />
<ul>
<li>Adaptability. Integrate different testing assets: desktop applications, web applications, mobile applications, services... Therefore, it must be able to support different tools and programming languages (adaptable to the needs of each test): SikuliX, WebDriver (Selenium), JMeter, SoapUI...</li>
</ul>
<ul>
<li>Configuration flexibility. Environment of the execution configurable (parametrizable): execute the same test with different parameters / properties, different runtime environments, different application properties...</li>
</ul>
<ul>
<li>Parallelization.</li>
</ul>
<ul>
<ul>
<li>"Fast enough" to be integrated into a CD</li>
</ul>
</ul>
<ul>
<ul>
<li>Running parallel test for different versions of the product. For example, we may need to do two releases at once (a patch and upgrade), the test platform should not be the bottleneck.</li>
</ul>
</ul>
<ul>
<li>Scalability. Test cases can grow, but the total execution time should be maintained.</li>
</ul>
<ul>
<li>Availability: the platform must have at least the same criticality as the rest of the tools that allow us to obtain a CD.</li>
</ul>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibm7HqDvf_f08vjCel90BARZH0dkWgDVO3ypD8IRbTyMQmgkF7rbTnNr47z61Pacj2D_2XUyFjN1SE0b_gGs9xipWuQKHySsdboGqaN1F_xC4pKF4aHHPtbSUZ8JUTi9qboadA4T-NcEmB/s1600/automatedPlatform.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibm7HqDvf_f08vjCel90BARZH0dkWgDVO3ypD8IRbTyMQmgkF7rbTnNr47z61Pacj2D_2XUyFjN1SE0b_gGs9xipWuQKHySsdboGqaN1F_xC4pKF4aHHPtbSUZ8JUTi9qboadA4T-NcEmB/s1600/automatedPlatform.jpg" /></a></div>
<br /></div>
<h3>From the reporting point of view</h3>
Finally, we have to think about monitoring the executions and in the generation of reports<br />
<ul>
<li>Capable to sending email reports/alerts.</li>
</ul>
<ul>
<li>Traceability:</li>
</ul>
<ul>
<ul>
<li>Visibility of the executions over the different environments to step into production.</li>
<li>Versioning test, test plans. The tests have to follow the same versions that you have in your product.</li>
</ul>
</ul>
<ul>
<li>Diagnostic. Easily diagnose issues, because the reason for having automated test is to find issues and to make finding issues easy (having logs...).</li>
</ul>
<ul>
<li>History. Historical repository of executions with details</li>
</ul>
<ul>
<li>Customizable reporting. </li>
<ul>
<li>Custom reports for managers, clients...</li>
<li>Testing coverage between versions.</li>
<li>Product Performance between version.</li>
<li>Compare different test executions over different software/product versions.</li>
</ul>
</ul>
<br />
Well as I said this is a simplified exercise, but I hope this list will be helpful as a checkpoint for Automated Test Platform requirements.
<br/>
<br/>s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-32186339926247632032016-02-07T20:13:00.001+01:002016-02-09T22:46:12.540+01:00Improve your Local Env with Docker+Jenkins+Selenium to achieve Continuous Delirery<div>
<span class="hps">The path to</span> <a href="http://martinfowler.com/bliki/ContinuousDelivery.html">Continuous Delivery</a> (<span class="hps">CD)</span> <span class="hps">happens to have</span> <span class="hps">stable</span> <span class="hps">execution results</span> <span class="hps">of automated</span> <span class="hps">test</span>, so will be ideal if the developers could pass the automated test on their local machine before they integrate their code with the base code. But if we want to execute the automated test on the developer local machine we have to be aware
of:</div>
<ol>
<li>The executions of the tests must be not intrusive, allowing the developers to focus on other tasks while the tests are executing.</li>
<li>The
solution must be easily adaptable to changes, for example, if new
tests suites are available or disabled, this <span class="sac" id="spans0e5" tooltip="{<b>doesn't have</b>} <i>substituye</i> <br/>{<b><s style='color:Red;'>not has</s></b>}: palabra incorrecta">doesn't have</span> to be an overhead
work for the developers to synchronize with their local environment.</li>
</ol>
<div>
Sometimes these points are difficult to accomplish, i.e. if we have more than 500 automated functional test to be tested with a real browser (e.g. Firefox). </div>
<div>
<br /></div>
<div>
Knowing the global solution explained in my previous post, it's easy with Docker and Jenkins to have a template that could build a "private platform" where execute 'locally' all the tests (unit, integrated, functional...)<br />
<div>
<br /></div>
You can see the simplified solution in the next diagram:</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj-53fRgn2Hv_laVOaFlCZWEcm9cZQOTvz0Q4WEwldFeqADAL-_D0ms9hX6C0qFTTg2FHd7TSeolv7XhOTM_hyphenhyphenMfQYbZuHQAjhcYPGYNx4ckOfM1w0gkEZ49gvCceLud7mH3a6DXUKWIQy/s1600/JenkinsConDockerEnLocal.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj-53fRgn2Hv_laVOaFlCZWEcm9cZQOTvz0Q4WEwldFeqADAL-_D0ms9hX6C0qFTTg2FHd7TSeolv7XhOTM_hyphenhyphenMfQYbZuHQAjhcYPGYNx4ckOfM1w0gkEZ49gvCceLud7mH3a6DXUKWIQy/s1600/JenkinsConDockerEnLocal.png" /></a></div>
<br /></div>
<div>
As you can see on the diagram, the solution is based on Docker compose which builds Jenkins in a Docker container: a Jenkins Master and n-slaves Jenkins (depending on configuration parameters). It will execute the test with Selenium/Firefox, where the test live in the local filesystem of the host. In this case, for convenience and not to overload the developers' machines, we won't test on IE (but we could use a Vagrant virtual-machine with Windows and IE)...<br />
<br />
The key points of this kind of configuration are:<br />
<ul>
<li>Run Automated Test in background.</li>
<li>Light GUI containers to run Firefox with Selenium.</li>
<li>Parallel execution of the tests. </li>
<li>Easy installation and updates.</li>
<li>We can see the visual errors of the navigation in the pdfs generated by the framework of test (<a href="http://s2o-bcn.blogspot.com.es/2016/01/continuous-integration-functional.html">see previous post</a>)</li>
</ul>
<h2>
Some Technical details of the solution</h2>
<h3>
Docker-Compose</h3>
<h3>
<div style="font-size: medium; font-weight: normal;">
<span style="font-size: small;"><span style="font-weight: normal;">With <a href="https://docs.docker.com/compose/">Docker-Compose</a> we have a simplified configuration for the developer:</span></span><br />
<div style="font-size: medium; font-weight: normal;">
</div>
</div>
<pre class="brush:bash"># Jenkins Master
jenkins:
image: s2obcn/jenkins
container_name: jenkins
ports:
- "8090:8080"
- "50000"
volumes:
- /home/s2o/vDocker/jenkins:/jenkins
env_file:
- jenkins-master.env
# Jenkins Slave
slave:
image: s2obcn/jenkins-swarm
links:
- jenkins:jenkins
volumes:
- /home/s2o/vDocker/jenkins_shared/workspace:/opt/jenkins/workspace
env_file:
- jenkins-slave.env
</pre>
</h3>
<h3>
Jenkins docker image with swarm plugin</h3>
<div>
Speed up the execution of the tests by running them in parallel,
grouping the tests by suites and executing any suite by a different job. A second level of parallelisms is splitting the execution of the jobs by different Jenkins slaves.<br />
<ul>
<li>In this case the Jenkins slaves will connect to the Jenkins master by the<a href="https://github.com/blacklabelops/jenkins-swarm"> Swarm plugin of Jenkins</a>:</li>
</ul>
</div>
<div>
<pre class="brush:bash">RUN wget --no-check-certificate --directory-prefix=${SWARM_HOME} \
http://maven.jenkins-ci.org/content/repositories/releases/org/jenkins-ci/plugins/swarm-client/${SWARM_VERSION}/swarm-client-${SWARM_VERSION}-jar-with-dependencies.jar && \
mv ${SWARM_HOME}/swarm-client-${SWARM_VERSION}-jar-with-dependencies.jar ${SWARM_HOME}/swarm-client-jar-with-dependencies.jar && \
mkdir -p ${SWARM_WORKDIR} && \
mkdir -p ${SWARM_WORKDIR}/workspace/{TEST_PROJECT} && \
chown -R jenkins:jenkins ${SWARM_HOME} && \
chown -R jenkins:jenkins ${SWARM_WORKDIR} && \
chmod +x ${SWARM_HOME}/swarm-client-jar-with-dependencies.jar</pre>
</div>
<h3>
Docker with the correct Firefox configuration</h3>
To get a custom profile with Firefox the best way is execute Firefox, change the configuration as needed and save the current profile for the next executions.<br />
<ul>
<li>Now I get Firefox running within a docker container and rendered by the local X Server, so in this way it can be easy configured:</li>
</ul>
<pre class="brush:bash">docker run -it --privileged -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -v /home/s2o/tmp/a:/opt/jenkins s2obcn/jenkins-swarm bash
</pre>
<h3>
Sharing local IDE workspace with Jenkins Job workspace</h3>
<div>
<ul>
<li>The test, to be executed, will be loaded from an SCM or shared from a local FS. The trick here is to share the workspace between all the jobs/Jenkins.</li>
</ul>
</div>
<h3>
Naming conventions (Jenkins with Job DSL Plugin)</h3>
<div>
<ul>
<li>The jobs to execute will have the same name of the suites to execute. </li>
<li>We can build/update the jobs in the local Jenkins with the plugin <a href="https://wiki.jenkins-ci.org/display/JENKINS/Job+DSL+Plugin">Job DSL</a>. </li>
</ul>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
</div>
<br />s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-2068582306341515412016-01-24T22:10:00.000+01:002016-01-25T23:29:21.058+01:00Continuous integration: Functional Testing - Distributed Testing with Selenium and JenkinsA way to distribute Selenium tests can be use <a href="https://code.google.com/p/selenium/wiki/Grid2">Selenium Grid</a> alone or <a href="https://wiki.jenkins-ci.org/display/JENKINS/Selenium+Plugin">Jenkins and the Selenium Jenkins plugin</a>. However if more control is required, there's another way with <b>Jenkins</b>. You can configure a Jenkins Master with <b>n-Jenkins Slaves</b> that will execute the Selenium tests like <b>local execution</b>. In other words, Jenkins Slave will execute exactly as developers do in their local environment without any overhead configuration.<br />
<br />
So, which are the pros to use this technique instead of Selenium Grid:<br />
<ul>
<li>Easy integration: it can be integrated seamlessly into the continuos integration (CI) of our product. </li>
<li>Distribution: the same infrastructure can be used to distribute the execution of ANY functional test (jMeter, SoupUI, Selenium...). </li>
<li>Dynamic: assignment different browsers capabilities test are more dynamic than with Selenium Grid. With Jenkins Master/Slave, the slave has the labels to conform different tests types that can be executed by any node. For example, the number of executors (instances of browsers) or node labels can be changed directly in Jenkins without restarting the node.</li>
<li>Reporting: the execution and post execution (reports..) are distributed overall Jenkins nodes. </li>
<li>Centralized control: the distribution control is centralized in Jenkins.</li>
</ul>
<div>
Knowing that solution, we can implement this solution with:</div>
<div>
<ul>
<li>TestNg as core test framework:</li>
<ul>
<li>Group functional test in suites (that will be executed directly by the Jenkins jobs).</li>
<li>Filter test execution by parameters ("@Test(groups='demoUser','pro'"... where we can have different kind of groups, such as different type of users, different environments... ) </li>
<li>Definition of executions "timeouts" (at different levels).</li>
<li>An easy way to execute the test (from maven, directly with java...)</li>
<li>Data Driven Test</li>
<li>Reports</li>
<li>...</li>
</ul>
<li>Test will be built following the Page Object Pattern. </li>
<li>A custom core framework that:</li>
<ul>
<li>Centralize configuration management of the test execution (main homepage, main browser type, user, password....).</li>
<li>Centralize the startup of the browser (select browser by configuration properties)</li>
<li>Automate the login of the test: every test will only take care of the page to test, navigation through the pages will managed by the core framework</li>
<li>Execution retry policy (you know that test over IE may fail without reason)</li>
<li>Manage errors </li>
<li>Data Driven Test: data stored in excels organized by 'tables'</li>
<li>Custom detailed reports</li>
<li>...</li>
</ul>
<li>Testlink as Test Management.</li>
</ul>
<div>
<br /></div>
<div>
This is a simplified picture of the platform to automate the execution of Selenium with Jenkins:</div>
</div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJAdpfOlxJGozhKqYA-jR_IUm9UkbLKCmuas5o5mUkhpRA1knJFvpZjxSbZiSv3vED6iHoV0OQIMe58NfK2D8OHw5w9FFdt3QbwAuJg5w6bExGdDMmhsi5lj2PQQZJgDv4UR2eXSAVujd8/s1600/automateJenkins.png" imageanchor="1"><img border="0" height="306" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJAdpfOlxJGozhKqYA-jR_IUm9UkbLKCmuas5o5mUkhpRA1knJFvpZjxSbZiSv3vED6iHoV0OQIMe58NfK2D8OHw5w9FFdt3QbwAuJg5w6bExGdDMmhsi5lj2PQQZJgDv4UR2eXSAVujd8/s640/automateJenkins.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
You can follow this <a href="http://www.guru99.com/maven-jenkins-with-selenium-complete-tutorial.html">tutorial</a> to configure Jenkins with Selenium and this other <a href="https://wiki.jenkins-ci.org/display/JENKINS/Step+by+step+guide+to+set+up+master+and+slave+machines">tutorial</a> to configure the Jenkins Slaves.<br />
<br />
To sum up, the main goal of this solution is to use the <b> Jenkins node</b><b> "labels"</b> to assign the web browser that will be executed by any node and configure the Jenkins Slaves to <b>execute the Selenium WebDriver</b> without problems (I will write a post about how to configure the Jenkins Slave properly to execute IE as a service without problems).<br />
<div>
<br /></div>
<div>
</div>
</div>
s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-56599239880119063612010-12-07T08:05:00.001+01:002010-12-09T01:10:15.084+01:00Flex: Chimp security solution (use it without metadata on source code!!!)<span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: 13px;">"<a href="http://code.google.com/p/flexible-chimp/">Chimp</a> is permission based filtering component for Adobe Flex and AIR. Applications implement Chimp by adding metadata within the Flex UIComponents. Based on the metadata it will remove components completely, enable/disable, and update visibility."</span><br />
<span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: 13px;"><br />
</span><br />
<div style="text-align: justify;">In this post I will show you an extension for the Chimp component that will provide a transparent implementation of the security for the developers. With this extension the permissions metadata is no longer needed to be in the source code. The permissions will be loaded dynamically at runtime.</div><br />
<br />
First of all, let me give you a short view of the architecture we are using in our applications:<br />
<div style="text-align: justify;">- the main application navigation is made in a <a href="http://flexlib.googlecode.com/svn/trunk/docs/flexlib/containers/SuperTabNavigator.html">superTabNaviagtion</a>: every conversartion (screen) is loaded in a separate tab.</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0FOC57bFerdiGolQ94ZitcoHcJ_GuHv9xv3bXeDWE4R6S7DphOODoKpG0jwnRgJ7hORW6eJLl_ZlJ8-ax6BV19ay73cdTV1oPOT4Xon8hoKU6i2v_HX2mHNiNS1qw84vvobJljPPj5CBN/s1600/loadTab.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="52" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0FOC57bFerdiGolQ94ZitcoHcJ_GuHv9xv3bXeDWE4R6S7DphOODoKpG0jwnRgJ7hORW6eJLl_ZlJ8-ax6BV19ay73cdTV1oPOT4Xon8hoKU6i2v_HX2mHNiNS1qw84vvobJljPPj5CBN/s400/loadTab.png" width="400" /></a></div><div style="text-align: justify;">This is done by the core of the architecture (our framework), every developer's team only have to take care of their conversations (screens), that will be loaded by the framework in a client workbench.</div><br />
<div style="text-align: justify;">What I will do is, before every new screen (new tab) is loaded, I will call a service that will give the permissions (permitted actions) for that screen and then I will set those permissions to the Chimp component.</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipvtYB6wCzD5bv32W6uYpTbH05s3Ek0UPxGj4xPyxuv9LhrrymTH609EAdq1hbxlq-Vx6sToVY94O6hNuWGRnYYqXGIN7IS2ObMPXlgJbdOPN8MwJfGK9rEjixJS68DMW6mJoTDsrBVsla/s1600/loadedTab.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="130" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipvtYB6wCzD5bv32W6uYpTbH05s3Ek0UPxGj4xPyxuv9LhrrymTH609EAdq1hbxlq-Vx6sToVY94O6hNuWGRnYYqXGIN7IS2ObMPXlgJbdOPN8MwJfGK9rEjixJS68DMW6mJoTDsrBVsla/s400/loadedTab.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: justify;">Of course, I will need a separate application to carry on those permissions actions of our components (that otherwise must to be written in the source code of the application as metadata), and this application will be managed by an administrator.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: justify;">Finally, the only thing needed for working correctly is that every button or component to be securiced must have an unique id in the whole application. This could be done easily with naming conventions.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The next code is added to Chimp.as:</div><pre class="brush:as3">/**
* Load chimp before the UIComponents are added with permission strings
*/
public static function load(permissions:ArrayCollection, metadataPermissions:Boolean=true):void {
if(permissions != null) {
_permissions = permissions;
_permissions.addEventListener(CollectionEvent.COLLECTION_CHANGE, updateDisplay);
} else {
permissions = new ArrayCollection();
}
_metadataPermissions= metadataPermissions;
//add chmip system add handler
FlexGlobals.topLevelApplication.addEventListener(Event.ADDED_TO_STAGE, processComponenet, true);
}
/**
* @author s2o
*
* <screen id="testId">
* <metadata name="Protected">
<arg key="permissions" value="admin">
<arg key="notInPermissionAction" value="removeFromLayout">
<arg key="componentId" value="adminButton">
</arg></arg></arg></metadata>
* </screen>
* @param screenActions
*
*/
public static function addScreenPermissionActions( screenActions:XML ):void{
var screenId:String = screenActions.@id;
for each (var metadata:XML in screenActions.descendants("metadata")) {
// the ChimpConstants.ACTION_REMOVE_CHILD is not considered
var chimpAction:ChimpAction = getAction(metadata);
chimpAction.parentId = screenId;
ChimpActionCache.instance.addDelayLoadAction(chimpAction);
}
}
/**
* @author s2o
*
* Removes permission from cache
* @param screenId
*
*/
public static function removeScreenPermissionActions(screenId:String):void {
ChimpActionCache.instance.freeCachedActionById(screenId);
}
//process ui object
private static function process(obj:Object):void {
if(obj is UIComponent) {
if (_metadataPermissions) {
processMetadataPermissions(obj);
} else {
processDelayPermissions(obj);
}
}
}
/**
* @author s2o
*
* @param obj
*
*/
private static function processDelayPermissions(obj:Object):void {
var comp:UIComponent = obj as UIComponent;
for each(var delayedChimpAction:ChimpAction in ChimpActionCache.instance.getDelayLoadActionById(comp.id)) {
delayedChimpAction.comp = comp;
doAction(delayedChimpAction);
// for updates display on changes to the roles
ChimpActionCache.instance.addAction(delayedChimpAction);
}
}
</pre>s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com3tag:blogger.com,1999:blog-3321514629934017493.post-50593391399916620402010-09-02T12:26:00.000+02:002010-09-14T15:54:32.249+02:00AndroMDA vs Acceleo (MDA)<div style="text-align: justify;"><span class="Apple-style-span" style="font-size: x-large;"><b>Objective</b></span></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">The aim of this paper is a brief introduction to MDA technology and a summary / comparison to the approachments to MDA of AndroMDA and Acceleo, intending to be a practical and understandable summary</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><span class="Apple-style-span" style="font-size: x-large;"><b>Introduction</b></span></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Model-driven architecture (MDA) is a software design approach for the development of software systems. It provides a set of guidelines for the structuring of specifications, which are expressed as models. It was launched by the Object Management Group (OMG) in 2001</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">The Model-Driven Architecture approach defines system functionality using a platform-independent model (PIM) using an appropriate domain-specific language (DSL).</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">One of the main aims of the MDA is to separate design from architecture. As the concepts and technologies used to realize designs and the concepts and technologies used to realize architectures have changed at their own pace, decoupling them allows system developers to choose from the best and most fitting in both domains. The design addresses the functional (use case) requirements while architecture provides the infrastructure through which non-functional requirements like scalability, reliability and performance are realized. MDA envisages that the platform independent model (PIM), which represents a conceptual design realizing the functional requirements, will survive changes in realization technologies and software architectures.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><i>To sum up:</i></div><br />
<ul><li style="text-align: justify;">Models are produced at business level, and translated into code using code generation tools</li>
<li style="text-align: justify;">The skill to move from model to implementation reduces most of the coding efforts</li>
<li style="text-align: justify;">By having the models in the first iteration of software construction, allows the possibility of obtaining an executable prototype system in early stages of project life cycle</li>
<li style="text-align: justify;">The transformation's rules for going from model to code are common to all similar projects, therefore the same rules apply to any project developing software allows a consistent software related to its quality and use of standards</li>
</ul><div style="text-align: justify;"><i><b>Pros of MDA:</b></i></div><br />
<ul><li style="text-align: justify;">Focus on the business</li>
<li style="text-align: justify;">Updated documentation. The process is, first change the model and then, regenerate the code.</li>
<li style="text-align: justify;">Less application errors: “The best way to avoid dangerous coding errors is to code less”</li>
<li style="text-align: justify;">Portability of the technology: If there's a new technology, by updating the PSM we can generate the code in the new technology</li>
</ul><div style="text-align: justify;"><i><b>Cons of MDA:</b></i></div><br />
<ul><li style="text-align: justify;">If we don't have code generated by the MDA, we can't apply MDA.</li>
<li style="text-align: justify;">The creation of components for the code automation is very complex</li>
<li style="text-align: justify;">Refactoring. A change in the model involves a change in the code, therefor the sincronization between the new code generted and the original code implemented by the developer is always a delicate step (despite having tools that facilitate this task, this step is always delicate).</li>
</ul><br />
<div style="text-align: justify;"><span class="Apple-style-span" style="font-size: x-large;"><b>ANDROMDA</b></span>:</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Web: <a href="http://www.andromda.org/index.php">http://www.andromda.org/index.php</a></div><div style="text-align: justify;">Creator: Matthias Bohlen</div><div style="text-align: justify;">Current state of the project:</div><br />
<ul><li style="text-align: justify;">AndroMDA 3.3 ( 2009-04-02) is the latest stable release (only supports UML 1.x)</li>
<li style="text-align: justify;">AndroMDA 3.4 -snapshot (2010-02-14) supports UML 2.x: all the modern versions of uml tools use UML 2.x</li>
<li style="text-align: justify;">AndroMDA 4: is on hold</li>
<li style="text-align: justify;">AndroMDA-eclipse plugin: seems to be hold, version 1.0-M3 since 2006</li>
</ul><br />
<div style="text-align: justify;"><b><i>Features</i></b>:</div><br />
<ol><li style="text-align: justify;">Open source framework that receives as an input a UML model that combined with suitable cartridges AndroMDA (model for technology mapping. NET, J2EE …), generates the source.</li>
<li style="text-align: justify;">AndroMDA cartridges are developed in velocty template (http://velocity.apache.org/). AndroMDA comes with a series of cartridges for the comprehensive code generation: BPM4Struts, jBPM, JSF, EJB, EJB3, Hibernate, Java, Meta, Spring, WebService and Xmlschema</li>
<li style="text-align: justify;">The sincronice of the model and the code generated by AndroMDA is done by taking into account that the code generated by AndroMDA consists of final classes that can't be modified by developers and abstract classes / interfaces, on which the developer implements the logic of business.That is the strategy for code generation is the direct heritange and delegation, therefore we depend on the final language and on the language structures to be able to generate final code, complex or not.</li>
<li style="text-align: justify;">AndroMDA is integrated with maven, but not with eclipse. Therefore, the management of new projects and code's generation will be done through the command line or ant task. For implementing a project with AndroMDA, we'll subdivid into: a MDA project (where AndroMDA generates code from the model) and a <b><span class="Apple-style-span" style="font-weight: normal;">Development Project (where development and testing take place).</span></b></li>
</ol><div><b></b><br />
<b></b><br />
<b></b><br />
<b></b><br />
<b><div style="text-align: justify;"><span class="Apple-style-span" style="font-weight: normal;"><b><i>Community support</i></b></span><span class="Apple-style-span" style="font-weight: normal;">: AndroMDA has maybe, one of biggest community of a MDA framework</span></div></b><br />
<div style="text-align: justify;"><br />
</div><div><div><br />
<div style="text-align: justify;"><span class="Apple-style-span" style="font-size: x-large;"><b>ACCELEO</b></span></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Web: <a href="http://www.eclipse.org/acceleo/">http://www.eclipse.org/acceleo/</a> (for version 2 <a href="http://www.acceleo.org/">http://www.acceleo.org</a>)</div><div style="text-align: justify;">Creator: Obeo</div><div style="text-align: justify;">Current state of the project:</div><br />
<ul><li style="text-align: justify;">Acceleo 3.0.0 ( 2010-06-23) is the latest stable release integrated into the eclipse release (part of the Eclipse Modeling project <a href="http://www.eclipse.org/home/categories/index.php?category=modeling">http://www.eclipse.org/home/categories/index.php?category=modeling</a>) . Not compatible with 2.x</li>
<li style="text-align: justify;">Acceleo 2.7.0 ( 02/04/2010). Compatible with the last release of eclipse but not integrated into.</li>
</ul><br />
<div style="text-align: justify;"><b><i>Features</i></b> (Acceleo 3):</div><br />
<ol><li style="text-align: justify;">Acceleo is an implementation of the Object Management Group (OMG) MOF Model to Text Language (MTL) standard. This component is an entirely new development of the OMG MOF Model to Text (Mof2Text) http://www.omg.org/spec/MOFM2T/1.0/ language. The implementation will be compliant</li>
<li style="text-align: justify;">The development of the code generation's modules is done by acceleo type projects in eclipse.There are currently very basic examples of code generation for Python and Java. In version 2 we can find more complex modules of generation. Acceleo focuses on supporting the creation of code generation, so it is really easy to create new modules: preview of the final result of the generation, debug, launch generation integrated in eclipse.</li>
<li style="text-align: justify;">The sincronization between the model and the code generated by Acceleo is done through special tag's (in the code generation templates) that shows the developer where to enter the specific new code. This makes that the final code generated by Acceleo can be very complex.. It could happened as well that a non-skillfull (clueless) developer removes special tags and then, the new code generated by Acceleo will not repect the code created by the developer.</li>
<li style="text-align: justify;">Code generation from a model and code generation module is done through an integrated implementation task in eclipse. And configured through a wizard of the eclipse. The implementation of an Acceleo project would be the usual with eclipse, because the generated code is integrated into the development of the developer.</li>
</ol><b></b><br />
<b></b><br />
<b></b><br />
<b></b><br />
<b><div style="text-align: justify;"><span class="Apple-style-span" style="font-weight: normal;"><b><i>Community support</i></b></span><span class="Apple-style-span" style="font-weight: normal;">: it's not as big as AndroMDA's community, but I have to say that was great to make a question in its forum and have a quick reponse</span></div><div style="text-align: justify;"><span class="Apple-style-span" style="font-size: x-large;"><span class="Apple-style-span" style="font-size: 19px; font-weight: normal;"><span class="Apple-style-span" style="font-size: medium;"><br />
</span></span></span><br />
<span class="Apple-style-span" style="font-size: x-large;"><span class="Apple-style-span" style="font-size: 19px; font-weight: normal;"><span class="Apple-style-span" style="font-size: medium;"><br />
</span></span></span></div><div style="text-align: justify;"><span class="Apple-style-span" style="font-weight: normal;"></span><br />
<span class="Apple-style-span" style="font-weight: normal;"><h2 style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: none; background-origin: initial; border-bottom-color: rgb(170, 170, 170); border-bottom-style: solid; border-bottom-width: 1px; color: black; font-size: 19px; font-weight: normal; margin-bottom: 0.6em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0.17em; padding-top: 0.5em; width: auto;"><span class="mw-headline" id="References"> <span class="Apple-style-span" style="font-size: small;"></span><br />
<span class="Apple-style-span" style="font-size: small;"><br />
<div style="line-height: 0.5cm; margin-bottom: 0cm; margin-left: 0px; margin-right: 0px; margin-top: 0px; orphans: 2; widows: 2;"><span style="font-family: arial, sans-serif;"><span style="font-size: small;"><span style="color: black;"><span style="font-style: normal;"><span style="font-weight: normal;">That's all folks! </span></span></span></span></span></div><div style="line-height: 0.5cm; margin-bottom: 0cm; margin-left: 0px; margin-right: 0px; margin-top: 0px; orphans: 2; widows: 2;"><span style="font-family: arial, sans-serif;"><span style="font-size: small;"><span style="color: black;"><span style="font-style: normal;"><span style="font-weight: normal;">Please if you see any incoherent, feel free to make corrections / suggestions.</span></span></span></span></span></div><div><span style="font-family: arial, sans-serif;"><span style="font-size: small;"><span style="color: black;"><span style="font-style: normal;"><span style="font-weight: normal;"><br />
</span></span></span></span></span></div><div><span style="font-family: arial, sans-serif;"><span style="font-size: small;"><span style="color: black;"><span style="font-style: normal;"><span style="font-weight: normal;"><br />
</span></span></span></span></span></div><div><span style="font-family: arial, sans-serif;"><span style="font-size: small;"><span style="color: black;"><span style="font-style: normal;"><span style="font-weight: normal;"> </span></span></span></span></span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: small;"><span style="color: black;"><span style="font-style: normal;"><span style="font-weight: normal;"></span></span></span></span></span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: small;"><span style="color: black;"><span style="font-style: normal;"><span style="font-weight: normal;"></span></span></span></span></span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: small;"><span style="color: black;"><span style="font-style: normal;"><span style="font-weight: normal;"></span></span></span></span></span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: small;"><span style="color: black;"><span style="font-style: normal;"><span style="font-weight: normal;"><div style="font-style: normal; font-weight: normal; line-height: 0.5cm; margin-bottom: 0cm; orphans: 2; widows: 2;"><span style="color: black;"><span style="font-family: sans-serif;"><span style="font-size: medium;"><span style="font-size: x-small;">References</span></span></span></span></div><div style="line-height: 0.5cm; margin-bottom: 0cm; orphans: 2; widows: 2;"><a href="http://en.wikipedia.org/"><span style="color: black;"><span style="font-family: sans-serif;"><span style="font-size: x-small;"><span style="font-style: normal;"><span style="font-weight: normal;">http://en.wikipedia.org/</span></span></span></span></span></a></div><div style="line-height: 0.5cm; margin-bottom: 0cm; orphans: 2; widows: 2;"><a href="http://www.eclipse.org/acceleo/"><span style="color: black;"><span style="font-family: sans-serif;"><span style="font-size: x-small;"><span style="font-style: normal;"><span style="font-weight: normal;">http://www.eclipse.org/acceleo/</span></span></span></span></span></a></div><div style="line-height: 0.5cm; margin-bottom: 0cm; orphans: 2; widows: 2;"><a href="http://www.acceleo.org/">http://www.acceleo.org</a><span style="color: black;"><span style="font-family: sans-serif;"><span style="font-size: x-small;"><span style="font-style: normal;"><span style="font-weight: normal;"> – forums</span></span></span></span></span></div><div style="line-height: 0.5cm; margin-bottom: 0cm; orphans: 2; widows: 2;"><span style="color: black;"><span style="font-family: sans-serif;"><span style="font-size: x-small;"><span style="font-style: normal;"><span style="font-weight: normal;"><a href="http://www.andromda.org/index.php">http://www.andromda.org/index.php</a> - forums</span></span></span></span></span></div><div style="font-style: normal; font-weight: normal; line-height: 0.5cm; margin-bottom: 0cm; orphans: 2; widows: 2;"><br />
</div></span></span></span></span></span></div></span></span><span class="Apple-style-span" style="font-size: small;"></span></h2></span></div></b></div></div></div>s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com1tag:blogger.com,1999:blog-3321514629934017493.post-13180052694670077142010-04-08T10:38:00.000+02:002010-04-20T09:57:29.581+02:00email: spring + velocityOne of the best ways to send e-mails is with spring and velocity template. With this technique sending an e-mail is as easy as make a jsp. <br />
<br />
In this sample I'm integrating the spring & velocity with struts2 and portlets, but could be extrapolated to any other environment.<br />
<br />
The recipe consists of:<br />
- applicationContextBeans.xml -> the sprig config file (the glue)<br />
- registrarse.vm -> a velocity template of our e-mail<br />
- EmailService.java & EmailServiceImpl.java -> the classes to apply the data to the template and send the e-mail. These classes will be the same for all the e-mails, so could be in a separate jar.<br />
- RegistrarseAction.java -> the struts2 action<br />
<br />
-applicationContextBeans.xml:<br />
<pre class="brush: xml"><bean id="emaiInformacionlService" class="es.project.miGestion.administracionDatos.service.EmailServiceImpl" scope="prototype">
<property name="velocityEngine" ref="velocityEngine"></property>
<property name="velocityTpl" value="es/project/velocity/solicitudInformacion.vm"></property>
<property name="inlineFiles">
<map>
<entry>
<key>
<value>id001</value>
</key>
<value>classpath:es/project/velocity/logoproject.png</value>
</entry>
</map>
</property>
</bean>
<bean id="emailRegistrarseService" class="es.project.miGestion.administracionDatos.service.EmailServiceImpl" scope="prototype">
<property name="velocityEngine" ref="velocityEngine"></property>
<property name="velocityTpl" value="es/project/velocity/registrarse.vm"></property>
<property name="inlineFiles">
<map>
<entry>
<key>
<value>id001</value>
</key>
<value>classpath:es/project/velocity/logoproject.png</value>
</entry>
</map>
</property>
</bean>
</pre><br />
- registrarse.vm:<br />
<pre class="brush: xml"><div id="logo">
<p align="right"><img src="cid:id001" /></p>
</div>
<div id="header">
<font size="2" style="font-family: Arial; color: rgb(51, 90, 143);">
A la Atenci&oacute;n del Servicio de Atenci&oacute;n Telef&oacute;nica
<br><br>
Cliente registrado en el formulario de la web.
#set ($bar = "cliente")
#if (${cliente} == $bar)
Ya es cliente de project y desea que un comercial se encarge de darle de alta en la Web de project:
#else
No es cliente de project y desea que un comercial se encarge de darle de alta en la Web de project:
#end
</font>
</div>
<br>
<div id="content">
<font size="2" style="font-family: Arial; color: rgb(51, 90, 143);">
<table class="width100" border="0" cellspacing="0" cellpadding="0">
<tr>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" width="110">Nombre</td>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >${nombre} ${apellidos}</td>
</tr>
<tr>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >DNI</td>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >${dni}</td>
</tr>
<tr>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >Direcci&oacute;n:</td>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >${direccion},${cp} ${poblacion} - ${pais}</td>
</tr>
<tr>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >Telefono:</td>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >${telefono}</td>
</tr>
<tr>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >Movil:</td>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >${movil}</td>
</tr>
<tr>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >Email:</td>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >${mail}</td>
</tr>
#if (${cliente} == $bar)
<tr>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >N&uacute;mero cuenta:</td>
<td style="font-size: 9pt; font-family: Arial; color: rgb(51, 90, 143);" >${numeroCuenta}</td>
</tr>
#end
</table>
</font>
</div>
<br>
<hr size="2" width="100%" align="left">
<span style="font-size: 7.5pt; font-family: Arial; color: rgb(51, 90, 143);">
.....
</span>
</pre><br />
- EmailServiceImpl.java <br />
<pre class="brush: java">...
private VelocityEngine velocityEngine;
private JavaMailSender javaMailSender;
private String velocityTpl;
private Map<String,Resource> inlineFiles;
/**
* Creaci�n y env�o de e-mail.
* @param from E-mail de origen
* @param recipients E-mails de destino
* @param subject Asunto del e-mail
* @param params Par�metros para la generaci�n del cuerpo del e-mail
*/
public void sendEmail(String from, String[] recipients, String subject, Map<String,Object> params) {
log.debug("sendEmail inicio");
final String f = from;
final String s = subject;
final Map<String,Object> p = params;
for(final String to : recipients){
MimeMessagePreparator preparator = new MimeMessagePreparator(){
public void prepare(MimeMessage mimeMessage) throws Exception{
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
helper.setFrom(f);
helper.setTo(to);
helper.setSubject(MimeUtility.encodeText(s, "iso-8859-1", "B"));
Map<String,Object> model = p;
String text = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine,velocityTpl,model);
helper.setText(text, true);
// añadiendo los ficheros "en línea"
if (getInlineFiles() != null) {
for (String key :getInlineFiles().keySet()) {
Resource value = getInlineFiles().get(key);
helper.addInline(key, value);
if (log.isDebugEnabled()) {
log.debug("File '" + value + "' added.");
}
}
}
}
};
javaMailSender.send(preparator);
}
log.debug("sendEmail fin");
}
/**
* Create and setup the mail sender component
* @param mailTO
*/
public void initializeJavaMailSender(MailTO mailTO){
log.debug("initializeJavaMailSender inicio");
//Create and setup the mail sender component
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(mailTO.getHostMail());
mailSender.setPort(Integer.valueOf(mailTO.getPort()));
mailSender.setUsername(mailTO.getUsername());
mailSender.setPassword(mailTO.getPassword());
//We need this setting for force Javamail to pass the login
boolean mailSmtpAuth = mailTO.getMailSmtpAuth().equals("true");
boolean starttls = mailTO.getStarttls().equals("true");
Properties props = new Properties();
if(mailSmtpAuth){
log.debug("mailSmtpAuth true:"+mailTO.getMailSmtpAuth());
props.setProperty("mail.smtp.auth", mailTO.getMailSmtpAuth());
}
if(starttls){
log.debug("starttls true:" + mailTO.getStarttls());
props.setProperty("mail.smtp.starttls.enable", mailTO.getStarttls());
}
mailSender.setJavaMailProperties(props);
javaMailSender = mailSender;
log.debug("initializeJavaMailSender fin");
}
...
</pre><br />
- RegistrarseAction.java<br />
<pre class="brush: java">// Enviar los datos por mail
emailRegistrarseService.initializeJavaMailSender(mailTO);
String[] recipients = mailTO.getToMail().split(";");
String[] emailUsuario = mail.split(";");
Map<String, Object> params = new HashMap<String, Object>();
params.put("cliente", cliente);
params.put("nombre", nombre);
params.put("apellidos", apellidos);
params.put("dni", dni);
params.put("direccion", direccion);
params.put("poblacion", poblacion);
params.put("mail", mail);
params.put("telefono", telefono);
params.put("pais", pais);
params.put("cp", cp);
params.put("movil", movil);
params.put("numeroCuenta", numeroCuenta);
emailRegistrarseService.sendEmail(mail, recipients,
mailTO.getSubject(), params);
</pre>s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-79437877832334623542010-03-15T11:25:00.000+01:002010-03-18T14:59:51.998+01:00Integrate struts2-jquery and portletsIn this <a href="http://code.google.com/p/struts2-jquery/wiki/FAQ">FAQ</a> we can see how to install the struts2-jquery plugin, but we have to make some little changes if we are developing porlets:<br />
<br />
1.Add the next servlet-mapping to the web.xml file:<br />
<pre class="brush: xml"><servlet>
<servlet-name>struts2servlet</servlet-name>
<servlet-class>org.apache.struts2.dispatcher.ng.servlet.StrutsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>struts2servlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>struts2Resources</servlet-name>
<servlet-class>org.apache.struts2.dispatcher.ng.servlet.StrutsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>struts2Resources</servlet-name>
<url-pattern>/struts/*</url-pattern>
</servlet-mapping>
</pre><br />
This could be done by a filter-mapping too, but with filter-mapping we can have some problems in a Websphere server.<br />
<br />
2.Define some pakage in the struts2 config to manage the ajax request<br />
<pre class="brush: xml" style="overflow: auto;"><package name="ajax" extends="json-default" namespace="/ajax">
...
</package>
</pre><br />
3.To make a valid ajax request from the portlet, all the request must be as the next examples:<br />
<pre class="brush: xml" style="overflow: auto;"><form id="compraVentaForm" action='<s:url value="/ajax/compraVentaSave.action"/>' method="post">
...
</form>
<s:url id="ordenesActivasResultado" value="/ajax/ordenesActivas.action"/>
<sj:div href="%{ordenesActivasResultado}" indicator="indicator" onCompleteTopics="completeDiv" reloadTopics="reloadDiv">
<img id="loading" src="<s:url value='/img/ajax-loader.gif'/>" alt="Loading..."/>
</sj:div>
</pre>s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com2tag:blogger.com,1999:blog-3321514629934017493.post-81152712882238546112010-02-27T23:04:00.000+01:002010-03-18T15:05:41.587+01:00SAP Java Connector (SAP JCo) : sampleHere's a sample code to get the currency list of the BAPI ZBAPI_GET_CURRENCY_LIST:<br />
<br />
<pre class="brush: java;">ArrayList desMoneda = new ArrayList();
ArrayList ideMoneda = new ArrayList();
//Creamos la función de la BAPI
com.sap.mw.jco.JCO.Function funcionDivisas = repository.getFunctionTemplate("ZBAPI_GET_CURRENCY_LIST").getFunction();
//Declaramos los parámetros que se le enviarán a la BAPI
com.sap.mw.jco.JCO.ParameterList listParams = funcionDivisas.getImportParameterList();
listParams.setValue("ES","LANGU");
//Ejecutamos la BAPI
connection.execute(funcionDivisas);
//Recuperamos la tabla de SAP
Table tablaDivisas = funcionDivisas.getTableParameterList().getTable("CURRENCYLIST");
desMoneda.add(Text.getText("language.messages", "ActividadRegistro.comboDivisa", oLocale));
ideMoneda.add("");
//Recorremos la tabla de divisas y seteamos los arrays del formulario
for (int i = 0; i < tablaDivisas.getNumRows(); i++){
ideMoneda.add(tablaDivisas.getValue("WAERS"));
desMoneda.add(tablaDivisas.getValue("LTEXT"));
tablaDivisas.nextRow();
}
</pre>
And here's the connectSap() and disconnectSap() functions:
<pre class="brush: java;">/** Conexion */
protected JCO.Client connection; // Connection con SAP
/** Repositorio */
protected IRepository repository; // Repostorio de funciones SAP
/**
* Iniciamos la conexion y el repositorio con el SAP
*
*/
public void connectSap(String client, String user, String pass, String lang, String host, String nSystem, String name) {
try {
/** Creamos la conexion con el SAP */
connection = JCO.createClient(client, user, pass, lang, host, nSystem);
connection.connect();
/** Creamos el repositorio con el SAP */
repository = new JCO.Repository(name, connection);
} catch(Exception e) {
log.error("Error -> connectSAP: " + e.getMessage(),e);
}
}
public void disconnectSap() {
if(connection != null) {
try {
connection.disconnect();
}catch(Exception e) {
log.error("Error -> disconnectSap: " + e.getMessage(),e);
}
}
}
</pre>s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-70601017818523053392010-01-18T19:17:00.000+01:002016-03-03T11:10:30.732+01:00WebService client: automating the generation of all java classesThe problem: <br />
Sometimes when we have to make a webservice client, we have the wsdl definition file and we have to choose some tecnique to generate the java client classes. But after all the code generated automatically by the framework we have an xmlStream to treat with... So finally, we have to implement the model classes of the part of the xml that we're interested in.<br />
<br />
To automate this final step we can generate the java classes to unmarshall the xml into java classes that matches data.<br />
<br />
In my last project I had the requirement to do this with axis (<a href="http://ws.apache.org/axis2/">Axis2</a>) and xmlbeans (<a href="http://xmlbeans.apache.org/">XMLBeans</a>). The webService was a Sharepoint service: lists.asmx. <br />
<br />
The solution: <br />
Create an xml ant to transform the wsdl to java: wsdl2java-SharepointList.xml. And create another xml ant to transform the xml returned by the webService: buildSharepointListItems.xml<br />
<br />
1.-wsdl2java-SharepointList.xml:<br />
<pre class="brush: xml;"><!DOCTYPE project>
<project name="wsdl2java-WebXXXX_Service" default="usage" basedir=".">
<property name="project-name" value="XXXX.ws.XXXXNet"/>
<property name="definicionDelWebService" value="input/webXXXX_Service.wsdl"/>
<property name="packageDestino" value="es.XXXX.ws.XXXXNet"/>
<property file="build.properties"/>
<property name="build" value="build"/>
<property name="src" value="src"/>
<property name="build.classes" value="build/classes" />
<path id="axis.classpath">
<pathelement location="build/classes" />
<fileset dir="${axis.home}/lib">
<include name="**/*.jar" />
</fileset>
<fileset dir="${xmlBeans.home}/lib">
<include name="**/*.jar" />
</fileset>
<pathelement location="${build.classes}" />
</path>
<path id="axis_client.classpath">
<pathelement location="build/classes" />
<fileset dir="${axis.home}">
<include name="**/*.jar" />
</fileset>
<fileset dir="lib">
<include name="*.jar" />
</fileset>
<pathelement location="${build.classes}" />
</path>
<target name="usage" description="Build file usage info (default task)">
<echo message=" " />
<echo message="${project-name} " />
<echo message="-------------------------------------------------------" />
<echo message=" " />
<echo message="Available Targets:" />
<echo message=" Cleaning up:" />
<echo message=" clean - Delete class files" />
<echo message=" " />
<echo message=" WSDL:" />
<echo message=" wsdl2java - Generate source from WSDL" />
<echo message=" " />
<echo message=" Compiling:" />
<echo message=" compile - Compiles the WSDL2Java source code" />
<echo message=" " />
<echo message=" jar final:" />
<echo message=" jar_wsdl - Generate the jar from WSDL2Java source code" />
</target>
<target name="prepare" >
<mkdir dir="${build.classes}" />
</target>
<target name="clean" >
<delete dir="${build}" />
<delete dir="output" />
</target>
<target name="wsdl2java" depends="clean,prepare">
<java classname="org.apache.axis2.wsdl.WSDL2Java" fork="true">
<classpath refid="axis.classpath"/>
<arg value="-uri"/>
<arg file="${definicionDelWebService}"/>
<arg value="-o"/>
<arg file="output"/>
<arg value="-d"/>
<arg value="xmlbeans"/>
<arg value="-p"/>
<arg value="${packageDestino}"/>
<arg value="-s"/>
<arg value="-u"/>
</java>
<!-- Move the schema folder to classpath-->
<move todir="${build.classes}">
<fileset dir="output/resources">
<include name="**/*schema*/**/*.class"/>
<include name="**/*schema*/**/*.xsb"/>
</fileset>
</move>
</target>
<target name="compile">
<echo message="Compiling wsdl2 files"/>
<javac
srcdir="output"
destdir="${build.classes}"
deprecation="true"
source="1.5"
target="1.5"
failonerror="true" debug="false">
<classpath refid="axis.classpath"/>
</javac>
</target>
<target name="jar_wsdl" depends="compile">
<jar jarfile="lib/${project-name}.jar" >
<fileset dir="${build.classes}" />
</jar>
</target>
<target name="all" depends="wsdl2java,jar_wsdl">
<echo message="Generando el jar desde el wsdl"/>
</target>
</project>
</pre>
<br />
<br />
2.-buildSharepointListItems.xml:<br />
<pre class="brush: xml;"><!DOCTYPE project>
<project name="buildSharepointListItems" default="usage" basedir=".">
<property name="project-name" value="torres.ws.shareponint.listItems"/>
<property name="xmlDeDatosInput" value="input/listItemsRetorn.xml"/>
<property name="xmlDeDatos" value="listItemsRetorn"/>
<property file="build.properties"/>
<property name="build" value="build"/>
<property name="src" value="src"/>
<property name="build.classes" value="build/classes" />
<path id="xmlBean.classpath">
<pathelement location="build/classes" />
<fileset dir="${xmlBeans.home}/lib">
<include name="**/*.jar" />
</fileset>
<pathelement location="${build.classes}" />
</path>
<target name="usage" description="Build file usage info (default task)">
<echo message=" " />
<echo message="${project-name} " />
<echo message="-------------------------------------------------------" />
<echo message=" " />
<echo message="Available Targets:" />
<echo message=" Cleaning up:" />
<echo message=" clean - Delete class files" />
<echo message=" " />
<echo message=" returned XML:" />
<echo message=" xml2xsd - Generate xsd from xml" />
<echo message=" " />
<echo message=" generate java binding:" />
<echo message=" xsd2java - Generate java from xsd" />
<echo message=" " />
<echo message=" Compiling:" />
<echo message=" compile - Compiles the xsd2java source code" />
<echo message=" " />
<echo message=" jar final:" />
<echo message=" exportJar - Generate the from WSDL2Java source code" />
</target>
<target name="prepare" >
<mkdir dir="${build.classes}" />
<mkdir dir="output" />
<mkdir dir="src" />
</target>
<target name="clean" >
<delete dir="${build}" />
<delete dir="output" />
<delete dir="src" />
</target>
<target name="xml2xsd" depends="clean,prepare">
<java classname="org.apache.xmlbeans.impl.inst2xsd.Inst2Xsd" fork="true">
<classpath refid="xmlBean.classpath"/>
<arg value="-design"/>
<arg value="rd"/>
<arg value="-outDir"/>
<arg file="src"/>
<arg value="-outPrefix"/>
<arg value="${xmlDeDatos}"/>
<arg value="${xmlDeDatosInput}"/>
</java>
</target>
<target name="xsd2java">
<java classname="org.apache.xmlbeans.impl.tool.SchemaCompiler" fork="true">
<classpath refid="xmlBean.classpath"/>
<arg value="-d"/>
<arg file="output"/>
<arg value="-javasource"/>
<arg value="1.5"/>
<arg value="-srconly"/>
<arg file="src"/>
<arg value="input/${xmlDeDatos}.xsdconfig"/>
</java>
</target>
<target name="compile" depends="xsd2java">
<echo message="Compiling files"/>
<javac
srcdir="output"
destdir="${build.classes}"
deprecation="true"
source="1.5"
target="1.5"
failonerror="true" debug="false">
<classpath refid="xmlBean.classpath"/>
</javac>
<!-- Move the schema folder to classpath-->
<move todir="${build.classes}">
<fileset dir="output">
<include name="**/*schema*/**/*.class"/>
<include name="**/*schema*/**/*.xsb"/>
</fileset>
</move>
</target>
<target name="exportJar" depends="compile">
<jar jarfile="lib/${project-name}.jar" >
<fileset dir="${build.classes}" />
</jar>
</target>
<target name="all" depends="xml2xsd,exportJar">
<echo message="Generando el jar desde el wsdl"/>
</target>
</project>
</pre>
<br />
3. And finally, the java that call the sharepoint service:<br />
<br />
<pre class="brush: java;">HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername(username);
auth.setPassword(password);
auth.setDomain(domain);
auth.setHost(host);
auth.setRealm(realm);
// Ensure NTLM authentication used
List<string> authPrefs = new ArrayList<string>(1);
authPrefs.add(AuthPolicy.NTLM);
auth.setAuthSchemes(authPrefs);
// Get stub
ListsStub stub = new ListsStub(sharepoinService + "_vti_bin/lists.asmx");
// Set authenticator
stub._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, auth);
// Get request and execute
com.microsoft.schemas.sharepoint.soap.GetListItemsDocument getListItems112 =com.microsoft.schemas.sharepoint.soap.GetListItemsDocument.Factory.newInstance();
GetListItems listaInput = GetListItems.Factory.newInstance();
listaInput.setListName(laguajeList[0]);
getListItems112.setGetListItems(listaInput );
GetListItemsResponseDocument listaResultado = stub.getListItems(getListItems112);
GetListItemsResult result = listaResultado.getGetListItemsResponse().getGetListItemsResult();
String resultString = result.xmlText();
log.debug(resultString);
resultString = resultString.replaceFirst("http://schemas.microsoft.com/sharepoint/soap/", "http://XXXXX/sharepoint/listItems");
ListitemsDocument root= ListitemsDocument.Factory.parse(resultString);
List<row> lista = root.getListitems().getData().getRowList();
</row></string></string></pre>
s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-69917616576548434912009-12-12T23:56:00.000+01:002010-03-18T15:11:27.863+01:00Spring + ibatis: calling a sql procedureThis post is a sample of a procedure call from ibatis, when we're under the spring influence!<br />
<br />
This is the <a href="http://ibatis.apache.org/ibator.html">ibator generator xml</a>. Used with the eclipse plugin.<br />
<br />
<pre class="brush: xml;"><?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ibatorConfiguration PUBLIC "-//Apache Software Foundation//DTD Apache iBATIS Ibator Configuration 1.0//EN" "http://ibatis.apache.org/dtd/ibator-config_1_0.dtd" >
<ibatorConfiguration >
<classPathEntry location="C:\eclipse\extra\BDD\SQLServer\sqljdbc_2.0\esn\sqljdbc4.jar" />
<ibatorContext id="test" >
<jdbcConnection driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver" connectionURL="jdbc:sqlserver://...:1433;databaseName=...." userId="..." password="..."/>
<javaModelGenerator targetPackage="es.test.model.WebProd" targetProject="test.negocio" />
<sqlMapGenerator targetPackage="es.test.dao.WebProd.sqlMap" targetProject="test.negocio" />
<daoGenerator targetPackage="es.test.dao.WebProd" targetProject="test.negocio" type="SPRING" />
<table schema="dbo" catalog="WebProd" tableName="aliasCuentas">
<property name="useActualColumnNames" value="true"/>
</table>
</ibatorContext>
</ibatorConfiguration></pre><br />
<h3>To the generated code of ibator, just add the next items:</h3><br />
<b>In WebProd_dbo_aliasCuentas_SqlMap.xml</b>:<br />
<pre class="brush: xml;"><parameterMap id="getAccountsCall" class="map">
<parameter property="titular" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/>
<parameter property="permiso" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/>
</parameterMap>
<resultMap id="cuentaAlias" class="es.test.model.WebProd.Aliascuentas">
<result property="aliasCuenta" column="aliasCuenta" />
<result property="idCuenta" column="idCuenta" />
</resultMap>
<procedure id="getAccounts" resultMap="cuentaAlias" parameterMap="getAccountsCall">
{call WebProd.dbo.sp_web_getCuenstasUsuarioAlias(?, ?)}
</procedure></pre><br />
<br />
<b>In AliascuentasDAO</b>:<br />
<pre class="brush: java;">List<es.test.model.WebProd.Aliascuentas> selectCuentas(Map example);</pre><br />
<br />
<b>In AliascuentasDAOImpl</b>:<br />
<pre class="brush: java;">public List<es.test.model.WebProd.Aliascuentas> selectCuentas(Map example) {
List<es.test.model.WebProd.Aliascuentas> list = getSqlMapClientTemplate().queryForList("WebProd_dbo_aliasCuentas.getAccounts", example);
return list;
}</pre><br />
<br />
<h3>Now, the configurations files of spring and the java source of the call.</h3><br />
<b>In applicationContext*.xml</b>:<br />
<pre class="brush: xml;"><bean id="aliascuentasDAO" class="es.test.dao.WebProd.AliascuentasDAOImpl">
<property name="sqlMapClient">
<ref bean="sqlMapWebProd"/>
</property>
</bean>
<bean id="aliasServicio" class="es.test.miGestion.administracionDatos.service.AliasCuentasServiceImpl">
<property name="aliascuentasDAO">
<ref bean="aliascuentasDAO"/>
</property>
</bean></pre><br />
<b>And finally the AliasCuentasServiceImpl.java</b>:<br />
<pre class="brush: java;">public List<Aliascuentas> getCuentas(String usuario) {
log.debug("getCuentas: inicio. usuario:" + usuario);
List<Aliascuentas> cuentasList;
Map<String, String> map = new HashMap<String, String>();
map.put("titular", usuario);
map.put("permiso", "Consultas");
cuentasList = aliascuentasDAO.selectCuentas(map);
log.debug("getCuentas: fin");
return cuentasList;
}</pre><br />
That's all!.s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-35689942630176356922009-11-13T23:51:00.000+01:002010-03-01T00:42:54.621+01:00Ajax Cross-domainWe have a web project that the 90% of the data it's taken from an outer domain. As the client forced us to make the queries directly to the other domain, we decided to use flXHR.<br />
<br />
“<a href="http://flxhr.flensed.com/">flXHR</a> is a *client-based* cross-browser, XHR-compatible tool for cross-domain Ajax (Flash) communication.”<br />
<br />
As we used <a href="http://jquery.com/">jquery</a> for build the tables, the right solution seems to use the flXHR jQuery plugin. And all seems right while we were testing in firefox and IE 8, but when we began to test it in IE7 we saw that "sometimes" after the refresh of the page... we had the CPU up to 100% and the IE7 blocked.<br />
<br />
After a refactorization and finally a total simplification of the page, we saw that the only way to use safely flXHR was putting the include of the flXHR.js file at the end of the page, or at least the last one of all the js includes of the page.<br />
<br />
The next simple example ends with 100% CPU if you refresh the page quickly so many times (<a href="http://www.sacristan.com.es/blog/ie2.html">source</a>):<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsPqz074QXhingU7n9pmNfXiaL-7iWTgTxTjIIvLj4HR2vDoEPCBZrfHWP3A5azQGfmPEVL_eeDjIHMG3eZTH9spN-eOhLqcqYmQWhUJrtUmq_yBkfBh4t4A0U7zopTP_KffMOwqfZdNBe/s1600-h/flXHR.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsPqz074QXhingU7n9pmNfXiaL-7iWTgTxTjIIvLj4HR2vDoEPCBZrfHWP3A5azQGfmPEVL_eeDjIHMG3eZTH9spN-eOhLqcqYmQWhUJrtUmq_yBkfBh4t4A0U7zopTP_KffMOwqfZdNBe/s320/flXHR.jpg" /></a></div><br />
<a href="http:///"></a>s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-1971690413989864192009-10-04T23:48:00.000+02:002010-03-18T15:13:41.360+01:00<h3 class="post-title entry-title"><a href="http://s2o-bcn.blogspot.com/2009/08/developing-portlets-using-eclipse-part.html">Developing Portlets using Eclipse. Part II</a></h3><br />
As I told you, the architecture that I use for these post, has iBATIS for it's persistence layer. <br />
<br />
The main reason for use this framework was that iBatis give you the flexibility of write your own optimized sql code, and an easy way to call directly to a sql procedure. Not to mention, the existence of iBator, the code generator for iBatis :)<br />
<br />
Spring will be a pivotal piece for the application, the reason for use of this framework it's as simple as I want to sleep as a baby. Some of the things that I want accomplish with spring is to have transparency over my data-source connection, jms..,, to make uncouple implementations from each other...<br />
<br />
Well, the first interaction between ibatis and spring it's done in the configuration files, the next example show you how to make a configuration that also makes the application container independent.<br />
<br />
Extract from applicationContext.xml:<br />
<pre class="brush: xml;"><!-- obtain datasource -->
<jee:jndi-lookup id="dataSourceWebProd" jndi-name="jdbc/webProd" cache="true" resource-ref="true" lookup-on-startup="false" proxy-interface="javax.sql.DataSource"/>
<!-- map iBatis to datasource -->
<bean id="sqlMapBaseWeb" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation"><value>classpath:/config/sqlmap-configWebProd.xml</value></property>
<property name="dataSource"><ref bean="dataSourceWebProd" /></property>
</bean>
<bean id="aliascuentasDAO" class="es.struts2PortletTemplate.dao.WebProd.AliascuentasDAOImpl">
<property name="sqlMapClient">
<ref bean="sqlMapWebProd"/>
</property>
</bean>
<bean id="informesServicio" class="es.struts2PortletTemplate.miGestion.informes.service.InformesServiceImpl">
<property name="aliascuentasDAO">
<ref bean="aliascuentasDAO"/>
</property>
</bean>
</pre><br />
sqlmap-configWebProd.xml:<br />
<pre class="brush: xml;"><settings cachemodelsenabled="true" enhancementenabled="true" usestatementnamespaces="true">
<sqlmap resource="es/struts2PortletTemplate/dao/WebProd/sqlMap/WebProd_dbo_aliasCuentas_SqlMap.xml">
</sqlmap></settings>
</pre><br />
And of course, you may well decide to use the Spring Framework's declarative transactions offer...<br />
<pre class="brush: xml;"><bean id="txManagerWebProd" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceWebProd"/>
</bean>
<tx:advice id="txAdviceWebProd" transaction-manager="txManagerWebProd">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="view*" read-only="true"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
</pre>s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-21279164235051377262009-09-12T01:59:00.000+02:002009-09-12T02:03:15.833+02:00Easy developing and debuging portlets with eclipse WTPThis little entry is just to show you how quickly I have my new environment up and running. As I told you in <a href="http://s2o-bcn.blogspot.com/2009/08/developing-portlets-using-eclipse-part.html">my firt pos</a>t, I develop the portlets with:<br />
<br />
Eclipse with WTP<br />
JetSpeed 2.2.0<br />
<br />
And I will use Struts2 (Struts 2.1.7) portltes (JSR 168)...<br />
<br />
The next log it's from a start up of the jetSpeed in debug mode.<br />
<br />
<span style="font-size: x-small;"><span style="color: red;">INFO: JetspeedContainerServlet: attemping to start Portlet Application at: /Struts2PortletTemplate</span><br style="color: red;" /><span style="color: red;">12-Sep-2009 01:49:02 org.apache.catalina.core.ApplicationContext log</span><br style="color: red;" /><span style="color: red;">INFO: JetspeedContainerServlet: started Portlet Application at: /Struts2PortletTemplate</span><br style="color: red;" /><span style="color: red;">12-Sep-2009 01:49:03 org.apache.catalina.core.ApplicationContext log</span><br style="color: red;" /><span style="color: red;">INFO: Initializing Spring root WebApplicationContext</span><br style="color: red;" /><span style="color: red;">12-Sep-2009 01:49:04 org.apache.catalina.core.ApplicationContext log</span><br style="color: red;" /><span style="color: red;">INFO: JetspeedContainerServlet: starting initialization of Portlet Application at: j2-admin</span><br style="color: red;" /><span style="color: red;">JetspeedContainerServlet: starting initialization of Portlet Application at: j2-admin12-Sep-2009 01:49:04 org.apache.catalina.core.ApplicationContext log</span><br style="color: red;" /><span style="color: red;">INFO: JetspeedContainerServlet: Could not yet start portlet application at: j2-admin. Starting back ground thread to start when the portal comes online.</span><br style="color: red;" /><br style="color: red;" /><span style="color: red;">12-Sep-2009 01:49:04 org.apache.catalina.core.ApplicationContext log</span><br style="color: red;" /><span style="color: red;">INFO: JetspeedContainerServlet: initialization done for Portlet Application at: j2-admin</span><br style="color: red;" /><span style="color: red;">JetspeedContainerServlet: initialization done for Portlet Application at: j2-admin</span><br style="color: red;" /><span style="color: red;">12-Sep-2009 01:49:04 org.apache.catalina.core.ApplicationContext log</span><br style="color: red;" /><span style="color: red;">INFO: JetspeedContainerServlet: attemping to start Portlet Application at: /j2-admin</span><br style="color: red;" /><span style="color: red;">12-Sep-2009 01:49:05 org.apache.coyote.http11.Http11Protocol start</span><br style="color: red;" /><span style="color: red;">INFO: Starting Coyote HTTP/1.1 on http-8080</span><br style="color: red;" /><span style="color: red;">12-Sep-2009 01:49:05 org.apache.jk.common.ChannelSocket init</span><br style="color: red;" /><span style="color: red;">INFO: JK: ajp13 listening on /0.0.0.0:8009</span><br style="color: red;" /><span style="color: red;">12-Sep-2009 01:49:05 org.apache.jk.server.JkMain start</span><br style="color: red;" /><span style="color: red;">INFO: Jk running ID=0 time=0/267 config=null</span><br style="color: red;" /><span style="color: red;">12-Sep-2009 01:49:05 org.apache.catalina.startup.Catalina start</span><br style="color: red;" /><span style="color: red;">INFO: Server startup in 14474 ms</span><br style="color: red;" /><span style="color: red;">12-Sep-2009 01:49:06 org.apache.catalina.core.ApplicationContext log</span><br style="color: red;" /><span style="color: red;">INFO: JetspeedContainerServlet: started Portlet Application at: /j2-admin</span><br style="color: red;" /></span><br />
<br />
It takes only <span style="color: red;">14474 ms</span><br />
can you do this with websphere?? ;)s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-7487426492887165002009-08-19T10:09:00.001+02:002009-08-19T17:43:56.440+02:00Developing Portlets using Eclipse. Part IOn this entries I will show you how to develop portlets, create and debug portlets, in Eclipse with the WTP plugin and <a href="http://portals.apache.org/jetspeed-2/">Jetspeed-2</a> . Lately I will deploy those portlets for the Websphere Portal 6.1.<br /><br />Some frameworks that I will use:<br /><ul><li><a href="http://ibatis.apache.org/index.html">iBatis</a><br /></li><li><a href="http://www.springsource.org/">Spring </a><br /></li><li><a href="http://struts.apache.org/2.x/">Struts2</a></li><li><a href="http://jquery.com/">jQuery</a></li></ul><span style="font-size:180%;">The environment</span><span style="font-size:180%;"></span><ul><li>Eclipse: download the last "<a href="http://www.eclipse.org/downloads/">Eclipse IDE for Java EE Developers</a>".<br /></li><li>Jetspeed-2: download the last version "<a href="http://portals.apache.org/jetspeed-2/download.html">Standard (Minimal) Installer</a>". I use the Derby (default) BDD.<br /></li></ul>Locations that I use to use with Linux:<br /><ul><li>/data/eclipse/eclipseWTP -> here's the eclipse.exe</li><li>/data/eclipse/eXtra/Jetspeed-2.2.0 -> for Jetspeed</li><li>/data/workspace/groupA -> for development</li></ul>Locations that I use to use with Windows:<br /><ul><li>c:\eclipse\eclipseWTP -> here's the eclipse.exe</li><li>c:\eclipse\eXtra\Jetspeed-2.2.0 -> for Jetspeed</li><li>c:\apps\workspace\groupA -> for developement<br /></li></ul>OK, now it's time to configure our eclipse:<br /><ul><li>Add a new server runtime. In eclipse "Preferences/Sever/Runtime Enviroment", add "Apache Tomcat v6.0" and use the installation of the Jetspeed as "Tomcat installation directory "/data/eclipse/eXtra/Jetspeed-2.2.0".<br /></li></ul><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGtFMFyzj-KftIugJW0p9LRYYdvtivGOSjgbOe8zY61-4aST4e4CQ9-IFZBK5Txba6I7W65zJ5KmalU7zvRmEVbPo2dY-Y9J4KBdOBfTGXh8ISrYR2hByeDXdfkaH8s5DMY8SfBhyphenhyphenpeTjE/s1600-h/jetspeed.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 327px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGtFMFyzj-KftIugJW0p9LRYYdvtivGOSjgbOe8zY61-4aST4e4CQ9-IFZBK5Txba6I7W65zJ5KmalU7zvRmEVbPo2dY-Y9J4KBdOBfTGXh8ISrYR2hByeDXdfkaH8s5DMY8SfBhyphenhyphenpeTjE/s400/jetspeed.jpg" alt="" id="BLOGGER_PHOTO_ID_5371683686369822162" border="0" /></a><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2YQEcD5qMBniJYrwRZzqyQ6lzi0ILtJkDFKhiIVVMpaDCxqh3N-5PCYMFflw3oa-x75KcBqkZgBkhXwM6oDOyeKV4_9ieqa9IkonPdsQ32s5EqK2vtEPEVO0LKsPnbeKUSucOkYsQ9eCF/s1600-h/jetspeed.jpg"></a><ul><li>Configure the new server. Here's the most important thing, just after we create the new server, we have to edit the server configuration and then "use Tomcat installation" (the default could be "use workspace") and change the "deploy path" to point where we had the "webapps" in our Jetspeed installation "<span style="font-style: italic;">/data/eclipse/eXtra/Jetspeed-2.2.0/webapps</span>". Also we have to change the timeout to start the server.<br /></li></ul><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh59Jl3X6zKJDMXx5h7hfi_CM69yKXgd4nLhkOkcwaB9IWk1ObG03sBis4khthJUH3utXvwRXfa5rwFYl-qNm1O735w8LVF4nLHhGrMNqMR5GdIG42NBZUR_Z7V7H-h_f-3YrxqKzSa7_w4/s1600-h/server.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 176px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh59Jl3X6zKJDMXx5h7hfi_CM69yKXgd4nLhkOkcwaB9IWk1ObG03sBis4khthJUH3utXvwRXfa5rwFYl-qNm1O735w8LVF4nLHhGrMNqMR5GdIG42NBZUR_Z7V7H-h_f-3YrxqKzSa7_w4/s400/server.jpg" alt="" id="BLOGGER_PHOTO_ID_5371683836676255506" border="0" /></a><br /><span style="font-size:180%;">The portlet</span><br /><br />In eclipse, create a new Dynamic Web Project with target runtime: "Jetspeed 2.2.0". Project name: Struts2PortletTemplate :)<br />OK, now change the project properties, in "Java build path"... I like this "Struts2PortletTemplate/WebContent/WEB-INF/classes" as the output folder.<br /><br />This will be the web.xml:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxr7_LzkIORpkfYfn3Kg-EsY8Z6medvu42CvM1fBu38VZKk4MbQ-tVCU82cUDIXLkOzDYrLeza8dY2oqoUh5Wm69jhXCB_g3kAPKePDTLSO2cm-mf_mUh6dU67YT18dk6jXapcqEkq-OIs/s1600-h/webX.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 396px; height: 400px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxr7_LzkIORpkfYfn3Kg-EsY8Z6medvu42CvM1fBu38VZKk4MbQ-tVCU82cUDIXLkOzDYrLeza8dY2oqoUh5Wm69jhXCB_g3kAPKePDTLSO2cm-mf_mUh6dU67YT18dk6jXapcqEkq-OIs/s400/webX.jpg" alt="" id="BLOGGER_PHOTO_ID_5371694053116688338" border="0" /></a>s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0tag:blogger.com,1999:blog-3321514629934017493.post-12371668896643944982009-06-16T05:54:00.000+02:002010-03-18T15:15:28.231+01:00MDA: the practical uml with AcceleoMaybe one of the best things of the MDA is that with a good template you can have all the test classes builded from just one click. Not to comment, the fact that the project will allways keep well documented with detailed uml :)<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggSDW6r-rqPyqxYC1fD0D343644NWmz9ZPUjHaVzxnho0ktsq4lTuvPQtYTo8gDJT0cUxhxEuNuhG_jMy1GMCwsFS7FPMiJZZQFeOetZyngEO9YQYEdD1TFFCvT4vrMkBLB4x7yxdF_xG5/s1600-h/uml.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggSDW6r-rqPyqxYC1fD0D343644NWmz9ZPUjHaVzxnho0ktsq4lTuvPQtYTo8gDJT0cUxhxEuNuhG_jMy1GMCwsFS7FPMiJZZQFeOetZyngEO9YQYEdD1TFFCvT4vrMkBLB4x7yxdF_xG5/s400/uml.png" width="400" /></a></div><br />
I used <a href="http://www.topcased.org/">topcased</a> as modeling tool and <a href="http://www.acceleo.org/pages/home/en">Acceleo</a> as code generator.<br />
<br />
It's very easy to extend the <a href="http://www.acceleo.org/pages/modules-repository/en">JEE Hibernate/Struts</a> module of Acceleo.<br />
<br />
A<span class="long_text" id="result_box"><span title="Como punto de partida, el módulo XXL ya trae de serie la generación de componentes básicos junit y html-unit.">s a starting point, this module ships with a basic generation of junit-unit and html-unit components. </span><span title="Pero no cuesta mucho extender estos componentes para obtener unos clases de prueba base más precisas.">But it's not hard to extend these components for generate more precise classes for testing. </span></span><span class="short_text" id="result_box"><span style="background-color: white;" title="Que nos ahorrará gran parte de la tediosa tarea de generación de clases de prueba">That will save us much of the tedious task of generating test classes</span></span><br />
<br />
Here is a sample:<br />
<br />
<pre class="brush: java;"><%--
sso 03-2008
--%>
<%
metamodel http://www.eclipse.org/uml2/2.0.0/UML
import es.sso.uml21.common.common
import es.sso.uml21.common.specifics
import es.sso.uml21.common.dataTypes
import es.sso.uml21.common.structure
import es.sso.uml21.common.services.StringServices
import es.sso.uml21.common.services.ListServices
import es.sso.uml21.common.services.Uml2Services
%>
<%script type="Class" name="fullFilePath"%>
<%if (hasStereotype(getProperty("Entity"))){%>
/<%daoTestPackage.toPath()%>/<%name%>DaoTest.java
<%}%>
<%script type="Class" name="generate" file="<%fullFilePath%>"%>
package <%daoTestPackage%>;
// <%startUserCode%> for import
<%if (attribute.select("type.name == 'Date'")){%>
import java.util.Date;
<%}%>
import junit.framework.Assert;
import junit.framework.TestCase;
import java.sql.SQLException;
import org.apache.commons.beanutils.DynaBean;
import com.mockrunner.jdbc.StatementResultSetHandler;
import com.mockrunner.mock.jdbc.MockResultSet;
import es.lacaixa.intranet.commons.beanutils.LazyDynaBean;
import es.lacaixa.intranet.test.BasicDAOTest;
import <%daoPackage%>.<%name%>Dao;
// <%endUserCode%> for import
public class <%name%>DaoTest extends BasicDAOTest {
/**
* Test the insert of the entity <%name%>.<br/>
* <ul><li>Step 1 : Create an entity</li>
* <li>Step 2 : Verificar datos insert</li></ul>
*/
public void testInsert() {
<%name%>Dao <%name.toLowerCase()%>Dao= new <%name%>Dao();
DynaBean dynaBean = new LazyDynaBean();
// <%startUserCode%>
<%for (attribute){%>
<%if (type.name == "String"){%>
dynaBean.set("<%name%>","<%i()+1%>");
<%}else if(type.name == "Date"){%>
<%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
<%}else if(type.name == "Integer"){%>
dynaBean.set("<%name%>",new Integer(<%i()+1%>));
<%}%>
<%}%>
// <%endUserCode%>
<%name.toLowerCase()%>Dao.insert(dynaBean);
String sqlQuery = "INSERT INTO <%tablaBDD%>";
verifySQLStatementExecuted(sqlQuery+" (<%attribute.name.sep(", ")%>) VALUES (<%paramInserts.substring(0,paramInserts.length()-2)%>)");
verifySQLStatementNotExecuted("UPDATE INTO <%tablaBDD%>a");
int numDeParametr=1;
<%for (attribute){%>
<%if (type.name == "String"){%>
verifySQLStatementParameter(sqlQuery, 0, numDeParametr, "<%i()+1%>");
numDeParametr++;
<%}else if(type.name == "Date"){%>
<%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
<%-- numDeParametr++; --%>
<%}else if(type.name == "Integer"){%>
verifySQLStatementParameter(sqlQuery, 0, numDeParametr, new Integer(<%i()+1%>));
numDeParametr++;
<%}%>
<%}%>
verifyNotCommitted();
verifyAllResultSetsClosed();
verifyAllStatementsClosed();
//verifyConnectionClosed();
}
/**
* Test the update of the entity <%name%>.<br/>
* <ul><li>Step 1 : Create an entity</li>
* <li>Step 2 : Verificar datos update</li></ul>
*/
public final void testUpdate() {
<%name%>Dao <%name.toLowerCase()%>Dao= new <%name%>Dao();
DynaBean dynaBean = new LazyDynaBean();
// <%startUserCode%>
<%for (attribute){%>
<%if (type.name == "String"){%>
dynaBean.set("<%name%>","<%i()+1%>");
<%}else if(type.name == "Date"){%>
<%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
<%}else if(type.name == "Integer"){%>
dynaBean.set("<%name%>",new Integer(<%i()+1%>));
<%}%>
<%}%>
// <%endUserCode%>
<%name.toLowerCase()%>Dao.update(dynaBean);
String sqlQuery = "UPDATE <%tablaBDD%> SET <%attribute.genComparator.sep(", ")%>";
verifySQLStatementExecuted(sqlQuery);
verifySQLStatementNotExecuted("UPDATE INTO <%tablaBDD%>a");
int numDeParametr=1;
<%for (attribute){%>
<%if (isUnique){%>
<%if (type.name == "String"){%>
verifySQLStatementParameter(sqlQuery, 0, numDeParametr, String.valueOf(numDeParametr));
numDeParametr++;
<%}else if(type.name == "Date"){%>
<%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
<%-- numDeParametr++; --%>
<%}else if(type.name == "Integer"){%>
verifySQLStatementParameter(sqlQuery, 0, numDeParametr, new Integer(numDeParametr));
numDeParametr++;
<%}%>
<%}%>
<%}%>
verifyNotCommitted();
verifyAllResultSetsClosed();
verifyAllStatementsClosed();
//verifyConnectionClosed();
}
/**
* Test the update of the entity <%name%>.<br/>
* <ul><li>Step 1 : Create an entity</li>
* <li>Step 2 : Verificar datos update</li></ul>
*/
public final void testDelete() {
<%name%>Dao <%name.toLowerCase()%>Dao= new <%name%>Dao();
DynaBean dynaBean = new LazyDynaBean();
// <%startUserCode%>
<%for (attribute){%>
<%if (isUnique){%>
<%if (type.name == "String"){%>
dynaBean.set("<%name%>","<%i()+1%>");
<%}else if(type.name == "Date"){%>
<%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
<%}else if(type.name == "Integer"){%>
dynaBean.set("<%name%>",new Integer(<%i()+1%>));
<%}%>
<%}%>
<%}%>
// <%endUserCode%>
<%name.toLowerCase()%>Dao.delete(dynaBean);
String sqlQuery = "DELETE FROM <%tablaBDD%> WHERE ";
verifySQLStatementExecuted(sqlQuery);
verifySQLStatementNotExecuted("UPDATE INTO <%tablaBDD%>a");
// <%startUserCode%>
<%for (attribute){%>
<%if (isUnique){%>
<%if (type.name == "String"){%>
verifySQLStatementParameter(sqlQuery, 0,<%i()+1%>,"<%i()+1%>");
<%}else if(type.name == "Date"){%>
<%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
<%}else if(type.name == "Integer"){%>
verifySQLStatementParameter(sqlQuery, 0, <%i()+1%>,new Integer(<%i()+1%>));
<%}%>
<%}%>
<%}%>
// <%endUserCode%>
verifyNotCommitted();
verifyAllResultSetsClosed();
verifyAllStatementsClosed();
//verifyConnectionClosed();
}
/**
* Test the search by id para <%name%>.<br/>
*/
public final void testFindById() {
<%name%>Dao <%name.toLowerCase()%>Dao= new <%name%>Dao();
DynaBean dynaBean = new LazyDynaBean();
// <%startUserCode%>
<%for (attribute){%>
<%if (isUnique){%>
<%if (type.name == "String"){%>
dynaBean.set("<%name%>","<%i()+1%>");
<%}else if(type.name == "Date"){%>
<%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
<%}else if(type.name == "Integer"){%>
dynaBean.set("<%name%>",new Integer(<%i()+1%>));
<%}%>
<%}%>
<%}%>
// <%endUserCode%>
<%name.toLowerCase()%>Dao.findById(dynaBean);
String sqlQuery = "SELECT <%attribute.name.sep(", ")%> FROM <%tablaBDD%> WHERE ";
verifySQLStatementExecuted(sqlQuery);
verifySQLStatementNotExecuted("UPDATE INTO <%tablaBDD%>");
// <%startUserCode%>
<%for (attribute){%>
<%if (isUnique){%>
<%if (type.name == "String"){%>
verifySQLStatementParameter(sqlQuery, 0,<%i()+1%>,"<%i()+1%>");
<%}else if(type.name == "Date"){%>
<%-- pValues.setDate(<%i()+1%>, new Date((String)dynaBean.get("<%name%>")); --%>
<%}else if(type.name == "Integer"){%>
verifySQLStatementParameter(sqlQuery, 0, <%i()+1%>,new Integer(<%i()+1%>));
<%}%>
<%}%>
<%}%>
// <%endUserCode%>
verifyNotCommitted();
verifyAllResultSetsClosed();
verifyAllStatementsClosed();
//verifyConnectionClosed();
}
}
<%script type="Property" name="exempleValues"%>
<%if (type.name == "Integer"){%><%name.uniqueCode()%><%}else{%>
<%if (type.name == "String"){%>"my<%name.firstUpper()%>"<%}else{%>
<%if (type.name == "Boolean"){%>true<%}else{%>
<%if (type.name == "Date"){%>new Date(0)<%}else{%>
<%if (type.name == "Float"){%><%name.uniqueCode()%>.0<%}else{%>
new <%type.name%>()<%}%><%}%><%}%><%}%><%}%>
<%script type="Property" name="exempleValues2"%>
<%if (type.name == "Integer"){%><%name.uniqueCode()%><%}else{%>
<%if (type.name == "String"){%>"second<%name.firstUpper()%>"<%}else{%>
<%if (type.name == "Boolean"){%>false<%}else{%>
<%if (type.name == "Date"){%>new Date(1)<%}else{%>
<%if (type.name == "Float"){%><%name.uniqueCode()%>.0<%}else{%>
new <%type.name%>()<%}%><%}%><%}%><%}%><%}%>
</pre>s2ohttp://www.blogger.com/profile/00886579875089628198noreply@blogger.com0