tag:blogger.com,1999:blog-47859136808164284712024-02-18T23:59:41.527-06:00Technology ArchitectureHelpful notes for me that may be useful for you...Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.comBlogger25125tag:blogger.com,1999:blog-4785913680816428471.post-31728781818085929342020-12-31T16:02:00.004-06:002021-06-15T12:36:35.371-05:00Installing Python and TensorFlow on MacOS Big Sur<p><span style="font-family: verdana;">This is a pretty quick tutorial on how to install the latest version of Python on MacOS, currently Big Sur, and then leverage the GPU for TensorFlow for your ML workloads. In case you have an M1 Mac, this will turn out to be your optimal way of running your ML loads locally.</span></p><p><span style="font-family: verdana;"><br /></span></p><h4 style="text-align: left;"><b><span style="font-family: verdana;">Installing Python the correct way on MacOS</span></b></h4><span style="font-family: verdana;">The best way to install python on MacOS is through pyenv. You can install pyenv via Brew</span><div><span style="font-family: verdana; font-size: x-small;"><br /></span></div><div><span style="font-family: verdana;"><p style="text-align: left;"><span> <span> </span></span>brew install pyenv</p></span></div><div><span style="font-family: verdana;">Once you have pyenv installed, make sure to install Xcode tools as follows:<br /></span><blockquote><p style="font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-family: verdana;">xcode-select --install </span></p></blockquote><p><span style="font-family: verdana;">You are now ready to install any version of Python. Given that we want to leverage TensorFlow, you will need to install a 3.8 version of Python ( the latest 3.9.0 version of python doesn't seem to work with the Apple fork of TensorFlow ).</span></p><blockquote><p style="font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-family: verdana;">export LDFLAGS="-L$(xcrun --show-sdk-path)/usr/lib" </span></p></blockquote><blockquote><p style="font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-family: verdana;">pyenv install 3.8.6</span></p></blockquote><p style="font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><b><span style="font-family: verdana;"><br /></span></b></p><div style="text-align: left;"><span style="font-family: verdana;">Add the following lines into your .bashrc or .zshrc:</span></div><p style="font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><span style="font-family: verdana;"><br /></span></p><p style="font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-family: verdana;"></span></p><blockquote><p style="font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-family: verdana;">eval "$(pyenv init -)"</span></p><p style="font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-family: verdana;">eval "$(pyenv virtualenv-init -)"</span></p></blockquote><p style="font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-family: verdana;"></span></p><div><span style="font-family: verdana;"><br /></span></div><p><span style="font-family: verdana;">That's it. You should be all set with Python 3.8.6. To leverage this version, you need to do one more thing at the command prompt:</span></p><blockquote><p style="font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-family: verdana;">pyenv global 3.8.6</span></p></blockquote><div><span style="font-family: verdana;"><br /></span></div><div><span style="font-family: verdana;"><b>Issues installing pyenv</b></span></div><div><span style="font-family: verdana;"><br /></span></div><div><span style="font-family: verdana;"><br /></span></div><div><span style="font-family: verdana;">If you're having issues installing pyenv, try the following command:</span></div><div><span style="font-family: verdana;"><br /></span></div><div><span style="font-family: verdana;"><div class="highlight js-code-highlight" style="border-radius: var(--radius); box-sizing: border-box; color: var(--syntax-text-color); font-family: -apple-system, system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; margin: 0 0 var(--content-rhythm) 0; overflow-wrap: initial; overflow-x: auto; position: relative;"><pre class="highlight shell" style="box-sizing: border-box; color: var(--syntax-text-color); font-family: var(--ff-monospace); font-size: 1em; margin-bottom: 0px; margin-top: 0px; overflow: auto; padding: var(--su-6);"><code style="background: rgba(0, 0, 0, 0.1); border-radius: var(--radius); box-sizing: border-box; color: var(--color-body-color); font-family: var(--ff-monospace); max-width: 100%; padding: 0px;"><span class="nv" style="box-sizing: border-box; color: var(--syntax-text-color);">CFLAGS</span><span class="o" style="box-sizing: border-box; color: var(--syntax-error-color);">=</span><span class="s2" style="box-sizing: border-box; color: var(--syntax-string-color);">"-I</span><span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">$(</span>brew <span class="nt" style="box-sizing: border-box; color: var(--syntax-error-color);">--prefix</span> openssl<span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">)</span><span class="s2" style="box-sizing: border-box; color: var(--syntax-string-color);">/include -I</span><span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">$(</span>brew <span class="nt" style="box-sizing: border-box; color: var(--syntax-error-color);">--prefix</span> bzip2<span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">)</span><span class="s2" style="box-sizing: border-box; color: var(--syntax-string-color);">/include -I</span><span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">$(</span>brew <span class="nt" style="box-sizing: border-box; color: var(--syntax-error-color);">--prefix</span> readline<span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">)</span><span class="s2" style="box-sizing: border-box; color: var(--syntax-string-color);">/include -I</span><span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">$(</span>xcrun <span class="nt" style="box-sizing: border-box; color: var(--syntax-error-color);">--show-sdk-path</span><span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">)</span><span class="s2" style="box-sizing: border-box; color: var(--syntax-string-color);">/usr/include"</span> <span class="nv" style="box-sizing: border-box; color: var(--syntax-text-color);">LDFLAGS</span><span class="o" style="box-sizing: border-box; color: var(--syntax-error-color);">=</span><span class="s2" style="box-sizing: border-box; color: var(--syntax-string-color);">"-L</span><span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">$(</span>brew <span class="nt" style="box-sizing: border-box; color: var(--syntax-error-color);">--prefix</span> openssl<span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">)</span><span class="s2" style="box-sizing: border-box; color: var(--syntax-string-color);">/lib -L</span><span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">$(</span>brew <span class="nt" style="box-sizing: border-box; color: var(--syntax-error-color);">--prefix</span> readline<span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">)</span><span class="s2" style="box-sizing: border-box; color: var(--syntax-string-color);">/lib -L</span><span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">$(</span>brew <span class="nt" style="box-sizing: border-box; color: var(--syntax-error-color);">--prefix</span> zlib<span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">)</span><span class="s2" style="box-sizing: border-box; color: var(--syntax-string-color);">/lib -L</span><span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">$(</span>brew <span class="nt" style="box-sizing: border-box; color: var(--syntax-error-color);">--prefix</span> bzip2<span class="si" style="box-sizing: border-box; color: var(--syntax-string-color);">)</span><span class="s2" style="box-sizing: border-box; color: var(--syntax-string-color);">/lib"</span> pyenv <span class="nb" style="box-sizing: border-box; color: var(--syntax-text-color);">install</span> <span class="nt" style="box-sizing: border-box; color: var(--syntax-error-color);">--patch</span> 3.8.0 < <<span class="o" style="box-sizing: border-box; color: var(--syntax-error-color);">(</span>curl <span class="nt" style="box-sizing: border-box; color: var(--syntax-error-color);">-sSL</span> https://github.com/python/cpython/commit/8ea6353.patch<span class="se" style="box-sizing: border-box; color: var(--syntax-literal-color);">\?</span>full_index<span class="se" style="box-sizing: border-box; color: var(--syntax-literal-color);">\=</span>1<span class="o" style="box-sizing: border-box; color: var(--syntax-error-color);">)</span>
</code></pre><div class="highlight__panel js-actions-panel" style="box-sizing: border-box; display: flex; position: absolute; right: 0px; top: 0px; visibility: hidden;"><div class="highlight__panel-action js-fullscreen-code-action" style="border-bottom-left-radius: var(--radius); box-sizing: border-box; display: flex; opacity: 0.9; overflow: hidden; padding: var(--su-2);"><svg class="highlight-action crayons-icon highlight-action--fullscreen-on" height="20px" viewbox="0 0 24 24" width="20px" xmlns="http://www.w3.org/2000/svg"><path d="M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"></path></svg></div></div></div><div class="highlight js-code-highlight" style="border-radius: var(--radius); box-sizing: border-box; color: var(--syntax-text-color); font-family: -apple-system, system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; margin: 0 0 var(--content-rhythm) 0; overflow-wrap: initial; overflow-x: auto; position: relative;"></div></span></div><h4 style="text-align: left;"><span style="font-family: verdana;"><br /></span></h4><h4 style="text-align: left;"><span style="font-family: verdana;">Installing TensorFlow</span></h4></div><div><span style="font-family: verdana;"><br /></span></div><div><span style="font-family: verdana;">Apple's fork of TensorFlow leverages the Mac GPUs instead of relying on the CUDA NVidea drivers. To install this forked project:</span></div><div><span style="font-family: verdana;"><br /></span></div><div><p style="text-align: left;"><span style="font-family: verdana; font-size: x-small;"></span></p><p style="text-align: left;"><span style="font-family: verdana;">bash -c "$(curl -fsSL https://raw.githubusercontent.com/apple/tensorflow_macos/master/scripts/download_and_install.sh)"</span></p><p></p><p><span style="font-family: verdana;">Make sure to activate your new python virtual environment for TensorFlow(depending upon where you have that directory setup):</span></p><p><span style="font-family: verdana; font-size: x-small;"></span></p><p style="text-align: left;"><span style="font-family: verdana; font-size: x-small;"></span></p><p style="text-align: left;"></p><p style="text-align: left;"><span style="font-family: verdana;"></span></p><blockquote><span style="font-family: verdana;">. ./bin/activate</span></blockquote><p></p><p></p><p></p><p></p><p><span style="font-family: verdana;">While running your code, you can look at the Mac Activity Monitor window to confirm that the GPU is getting leveraged ( Cmd+4).</span></p><p> </p></div>Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-24795766664631236072014-09-15T16:41:00.002-05:002014-09-15T16:46:54.320-05:00Getting your local user site available through native Apache on OS X (10.9,10.10)<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Edit the following files to get your local user site working:<br />
<br />
In http.conf, uncomment the following lines:<br />
<br />
<b>LoadModule userdir_module libexec/apache2/mod_userdir.so</b><br />
<br />
# User home directories<br />
<b>Include /private/etc/apache2/extra/httpd-userdir.conf</b><br />
<br />
In the following file - "/private/etc/apache2/extra/httpd-userdir.conf", uncomment the following line:<br />
<br />
<b>Include /private/etc/apache2/users/*.conf</b><br />
<br />
In your /private/etc/apache2/users directory, create a file with the syntax "<b>your_username</b>.conf". Note to replace the "your_username" with your actual username.<br />
<br />
In this file, add the following entries (note again to change the "your_username" entry).<br />
<pre><directory "/Users/your_username/Sites/">
Options Indexes MultiViews
AllowOverride None
Require all granted
#Order allow,deny
#Allow from all
</directory>
</pre>
</div>
</div>
<br />
<br />
This is the quickest way to expose your local Sites directory through Apache. You can now access your local directory through a url: <b>http://localhost/~your_username/</b><br />
<br />
You can further refine access rights, but this is the quickest way to get the behavior of user account web sharing back into OS X.<br />
<br /></div>
Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-29453829140843434152013-11-12T12:39:00.002-06:002013-11-12T12:39:26.866-06:00Linking frameworks to app bundles in Cocoa (via Xcode)<div dir="ltr" style="text-align: left;" trbidi="on">
If you're looking to link a framework to an app bundle, here's the easiest way to achieve it in 3 quick steps (applies for OS X 10.5 and up):<br />
<br />
<br />
<ul style="text-align: left;">
<li>For the framework you're linking, setup the installation directory with @rpath <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbVY3S_UF8UizUM3dmDkIwl3gc_yQnSd9SLJmC72PMAjYTctQYIWNZEAxBSs3JOrVODVoGXZYjP6t18rL5atqTE4aLlVwVQn-Zg_UpkaJa1ZXqt3sRZR0qoiFdG_iLwmzKLwUYLPw5DlKT/s1600/Screen+Shot+2013-11-12+at+10.30.41+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="15" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbVY3S_UF8UizUM3dmDkIwl3gc_yQnSd9SLJmC72PMAjYTctQYIWNZEAxBSs3JOrVODVoGXZYjP6t18rL5atqTE4aLlVwVQn-Zg_UpkaJa1ZXqt3sRZR0qoiFdG_iLwmzKLwUYLPw5DlKT/s320/Screen+Shot+2013-11-12+at+10.30.41+AM.png" width="320" /></a></li>
<li>For the application that's going to use the framework</li>
<ul>
<li>Copy the framework to the Frameworks directory under the app bundle<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIdtlFSRVbK1CZXlZ1Q8YWvahyN3DBglEx4oPpjpZaL6eZ75Ny7o3EEj8GjpC4vGZ3jockn6S_0sQJoUjKEUNjGY8gf29xDY8SvNsG62FJqqFW0gppy9xI6Mj8-0v1vgn1XyaVCj_2oASp/s1600/Screen+Shot+2013-11-12+at+10.33.47+AM.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: 1em; text-align: center;"><img border="0" height="114" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIdtlFSRVbK1CZXlZ1Q8YWvahyN3DBglEx4oPpjpZaL6eZ75Ny7o3EEj8GjpC4vGZ3jockn6S_0sQJoUjKEUNjGY8gf29xDY8SvNsG62FJqqFW0gppy9xI6Mj8-0v1vgn1XyaVCj_2oASp/s320/Screen+Shot+2013-11-12+at+10.33.47+AM.png" width="320" /></a></li>
<li>Add the following entry into the App's Linking section. Essentially where to look for the framework within the bundle</li>
<li><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitr7Oa_jJgcjiNDrwe-Y5DyYqIW2K8zuE7pj7fdt46B5y0dpD6Ma0MYCo9EcRlk2XxubYr3MrAxjvFuKzVV667PwT5fkjWxHE499Rga48BdTXbEctOVI2tTPIue9wZnt3-_XCXyQwMFPsd/s1600/Screen+Shot+2013-11-12+at+10.35.39+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="52" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitr7Oa_jJgcjiNDrwe-Y5DyYqIW2K8zuE7pj7fdt46B5y0dpD6Ma0MYCo9EcRlk2XxubYr3MrAxjvFuKzVV667PwT5fkjWxHE499Rga48BdTXbEctOVI2tTPIue9wZnt3-_XCXyQwMFPsd/s320/Screen+Shot+2013-11-12+at+10.35.39+AM.png" width="320" /></a></li>
</ul>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIdtlFSRVbK1CZXlZ1Q8YWvahyN3DBglEx4oPpjpZaL6eZ75Ny7o3EEj8GjpC4vGZ3jockn6S_0sQJoUjKEUNjGY8gf29xDY8SvNsG62FJqqFW0gppy9xI6Mj8-0v1vgn1XyaVCj_2oASp/s1600/Screen+Shot+2013-11-12+at+10.33.47+AM.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><br /></a></div>
<div>
And that's it - you're done. Lots of articles on the web on this (and of-course Apple's documentation).</div>
</div>
Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-52004550088584219872010-05-06T17:37:00.004-05:002010-05-08T23:22:59.940-05:00Aspiring to be a good Technical Architect?If you are aspiring to be a good architect in your organization or you feel that you're always struggling to make ends meet with Business requirements on one hand and your love for technology, this article at InfoQ by Andres Kutt really is something you need to read. I thought it to be very pragmatic advice for any architect (junior/senior) looking to get better at his/her trade. Read on - <br /><br /><a href="http://www.infoq.com/articles/learnings-five-years-skype-architect#view_56243">InfoQ: Learnings from Five Years as a Skype Architect</a><br /><br />- AmitAmithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-77913365180061104082009-09-15T15:27:00.000-05:002009-09-16T09:24:34.128-05:00Comparing Metro and CXFOver the past couple of weeks, I have been doing some research on Metro and CXF to find out some performance nos and see if there's a clear advantage in using one over the other for JAX-WS compliant service. In short, Metro definately was faster than CXF (untuned or out of the box). Here's a chart I put together showing the numbers - I ran the same call in a loop, making 100 serial calls.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYl-vwhcWQ1oQps8fJwMOxfQ0tpiMpmsFAxI4O5TG6516kxOwFzvcuhiyCdEoP8fREfJiBWCQYemt2TDXbXcOb6EPhPv-hoihGbswhNWQDBjzt4zp61fl_bMRr_FY0s_WX8GWUVnRBrGm3/s1600-h/Web+Service+Comparison.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 262px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYl-vwhcWQ1oQps8fJwMOxfQ0tpiMpmsFAxI4O5TG6516kxOwFzvcuhiyCdEoP8fREfJiBWCQYemt2TDXbXcOb6EPhPv-hoihGbswhNWQDBjzt4zp61fl_bMRr_FY0s_WX8GWUVnRBrGm3/s400/Web+Service+Comparison.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5381136154572683426" /></a><br /><center><span style="font-style:italic;">(All timings are in seconds)</span></center><br />The data was collected on a Toshiba Dual Core 2.1 Gz, 2GB RAM Tablet running Windows XP with the services hosted in Weblogic 10.3. The service itself did not do much in terms of functionality but to populate some in-memory data into the service response. So these times would not necessarily match true functional service times. <br /><br />I also took a look at development simplicity as the other key measure in determining the viability of the 2 libraries in the enterprise. I took the WSDL first approach in the development of these services, and found that CXF was a little easier to work with than Metro. Code generation and configuration were the 2 key factors here and both had some quirks here (with namespaces especially). CXF, out of the box integrates well with Spring. Metro doesn't though there is some hook that has been developed for it (though the initial version had a memory leak) - I did not try Spring integration with Metro.<br /><br />In terms of functionality and supporting the WS-* standards, Metro definately has it all, while CXF is catching up. To me the key WS standards are WS-Security/WS-Policy, WS-Reliability & WS-Transaction. While Metro supports them all being a reference implementation for the spec, CXF supports some parts of WS-Security/WS-Policy while it does not support WS-Transaction at this point.<br /><br />Overall, I still prefer CXF over Metro, though it seems like Metro looks a winner in all key categories I considered. At the end of the day, the differences are marginal and really depend upon what your needs are from a project perspective. What I mean here is that if you are looking at other things - eg. an ESB maybe (though management hates that word now, so be careful on that one...:)), for your project, then CXF fits in very well since it is a part of the Apache FUSE project. For Metro, Sun's(or Oracle) libraries are under a binary license (BCL), so that may be an issue to you if you are looking to change code (sometimes to fix a problem), but other than that, both libraries are solid and will probably both have equal adoptance across the enterprise space. While it may be a no brainer that if you were using XFire before, you should move to CXF now, performance wise, don't expect any difference (in-fact XFire was actually marginally faster over CXF). One thing I do need to play with here is the tuning recommendations on marshalling/unmarshalling of Xml in CXF that the project site talks about when using JAXB. I will post that information later since currently the documentation on it is really lacking (besides this - <a href="http://sxc.codehaus.org/JAXB">SXC</a>).<br /><br />Hope this post helps you make a choice - if its not helped, then its probably because both libraries are equally good - though I will say that Apache Axis definately has fallen behind.Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-53799486355116001692009-09-13T16:37:00.000-05:002009-09-16T09:24:00.613-05:00Sync your Outlook Calender on an iPod Touch with Exchange even with the iPhone 3.1 update<div align="justify"><br />Thought I would blog about this since many people are feeling the pinch from the latest iPhone 3.1 OS update that happened last Friday. While my solution may not be perfect, it works and helps you continue to sync your iPod touch or old iPhone 3G with your enterprise Exchange server that requires your device to encrypt your data. As you may be aware, the 3.1 OS update fixed a loophole Apple had introduced, for maybe the first time, in its product line. Old devices were allowed to sync with Exchange 2007 servers even if the servers required the hardware to require encryption of the data. In general when iPod Touch/iPhone communicated with Exchange, they wrongly stated to the Exchange server that they supported encryption. That is what allowed these devices to work with Exchange even though your enterprise policy required that such mobile devices store their data in an encrypted format. Apple has recently fixed this - meaning all these old devices, except the iPhone 3GS, won't lie about their encryption offering anymore. As a result of this, if your Exchange server requires encryption, your device will probably not sync with Exchange. So what do you do - and the option to get a 3GS makes no sense to you - well, then you workaround it of-course, because there was another feature added into the iPhone 3.0 OS upgrade that allows you to sync with Google Calender (using CalDAV) - and I believe you can sync with Yahoo Calendar too. Once again indirection solves the issue. You download <a href="http://dl.google.com/googlecalendarsync/GoogleCalendarSync_Installer.exe">Google Calendar Sync</a>. This allows all your appointments in Outlook to be synced with Google calendar. Then setup your ipod touch or iphone to sync with Google Calendar. Here are the steps for that - <br />This is how I configured CalDAV for Google Calendar on my iPod Touch:<br /><pre><br />Go to Settings > Mail, Contacts, Calendars<br />Tap "Add Account...", then "Other"<br />Under Calendars, "Add CalDAV Account"<br />Enter account information:<br />Server: www.google.com<br />User Name: [your username]<br />Password: [your password]<br />Description: [e.g. Personal]<br />Tap "Next"<br /></pre><br /><br />Hopefully, this option will help you out. Since CalDAV can be setup to use SSL, the appointment information can be securely pulled down. However, your enterprise still may not want your calendar information replicated to an outside site (in this case Google) for whatever reason. So be sure to confirm that this is considered a viable fallback option in your enterprise before you go ahead with it.<br /><br />While this helps with appointments/meetings which it really what I find useful on the iPod Touch, the iPhone users may be making use of the Mail sync function as well - and there really isn't a solution for that besides upgrading to 3GS. That's why I recommend this solution more for the iPod Touch users than the iPhone users.<br /></div>Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-81214960600809110912009-04-21T13:01:00.011-05:002009-04-21T22:55:57.573-05:00Using antlib to work with MavenIf you are using ant to build your project, you may want to start looking at moving away from ant and leverage Maven instead. I've been using Maven for about a year now and after the initial pains in understanding and building a complex project with Maven, I have understood and started liking what it has to offer. However, for those still stuck in the Ant world, you can still leverage the <a href="http://maven.apache.org/ant-tasks/usage.html">Antlib library</a> to leverage the dependency management capabilities of Maven. The best thing is that if you use Eclipse, you can also leverage the m2eclipse plugin for maven for projects using antlib. This helps get rid of all your dependent 3rd party jars embedded in your project.<br /><br />So if you have a JEE project - typically one that builds a separate WAR and EAR file, you will probably need 3 Maven POM files.<pre><br />---MyProject<br /> |<br /> ---web<br /> | |_<br /> | pom.xml<br /> |<br /> ---ear<br /> | |_<br /> | pom.xml<br /> |<br /> ---pom.xml <--(toplevel pom) <br /> |<br /> ---build.xml<br /></pre><br />All that's required in the top level pom is the following:<pre><br /><project xmlns="http://maven.apache.org/POM/4.0.0" xsi="http://www.w3.org/2001/XMLSchema-instance" schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><br /> <modelversion>4.0.0</modelversion><br /> <groupid>MyProject</groupid><br /> <artifactid>MyProject</artifactid><br /> <packaging>pom</packaging><br /> <version>1.0.0</version><br /> <modules><br /> <module>web</module><br /> <module>ear</module><br /> </modules><br /></project></pre><br />The web and ear directories will have a POM file depicting the dependencies for these respective artifacts. So for example, the WAR pom file could look like:<pre><br /><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br /> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><br /> <modelVersion>4.0.0</modelVersion><br /> <groupId>com.mycompany.myproject</groupId><br /> <artifactId>myproject-war</artifactId><br /> <version>1.0.0</version><br /> <packaging>war</packaging><br /> <dependencies><br /> <!-- Application specific --><br /> <dependency><br /> <groupId>struts</groupId><br /> <artifactId>struts</artifactId><br /> <version>1.2.8</version><br /> </dependency><br /><br /> <!-- provided --><br /> <dependency><br /> <groupId>javax.servlet</groupId><br /> <artifactId>servlet-api</artifactId><br /> <version>2.3</version><br /> <scope>provided</scope><br /> </dependency><br /> </dependencies><br /><br /></project></pre><br />Once you have these POM files setup, you can enable Maven support for the project using m2Eclipse. The "update configuration" and "update dependencies" options available through m2eclipse should create a CLASSPATH variable for your project with jars included based on those depicted in the WAR and EAR POM files. <br /><br />Now for your ant scripts to work with Maven and these POM files, here's what the ant script could look like:<pre><br /><?xml version="1.0" encoding="UTF-8"?><br /><project basedir="." default="buildAll" name="MyProject" xmlns:artifact="urn:maven-artifact-ant"><br /> <!-- Antlib --><br /> <path id="maven-ant-tasks.classpath" path="lib/maven-ant-tasks-ext-1.0.0.jar" /><br /> <typedef resource="org/apache/maven/artifact/ant/antlib.xml" <br /> uri="urn:maven-artifact-ant" <br /> classpathref="maven-ant-tasks.classpath" /><br /> <artifact:pom id="maven.war.project" file="${web.dir}/pom.xml"/><br /> <artifact:pom id="maven.ear.project" file="${ear.dir}/pom.xml"/> <br /> <artifact:dependencies pathId="war.dependency.pathset"><br /> <artifact:pom refid="maven.war.project" /><br /> </artifact:dependencies><br /> <artifact:dependencies pathId="ear.dependency.pathset"><br /> <artifact:pom refid="maven.ear.project" /><br /> </artifact:dependencies><br /> <br /> <br /> <target name="compile" depends="prepare"><br /> <condition property="debug.flag" value="on"><br /> <istrue value="${localbuild}" /><br /> </condition><br /> <condition property="debug.flag" value="off"><br /> <isfalse value="${localbuild}" /><br /> </condition><br /> <echo>Compiling source files, debug turned on</echo><br /><br /> <!-- Load dependency set --><br /> <javac debug="on" deprecation="${deprecation.flag}" destdir="${classes.dir}" optimize="${optimize.flag}" source="1.6" target="1.6"><br /> <src path="${gensrc.dir}" /><br /> <src path="${src.dir}" /><br /> <exclude name="${cvs.dirs}" /><br /> <classpath refid="war.dependency.pathset" /><br /> <classpath refid="ear.dependency.pathset" /><br /> </javac><br /> </target><br /><br /> <target name="buildWebModule" description="Create the Project Web WAR" depends="compile"><br /> <!-- Copy dependencies to temporary web lib --><br /> <artifact:dependencies filesetId="war.dependency.fileset" useScope="runtime"><br /> <artifact:pom refid="maven.war.project" /><br /> </artifact:dependencies><br /> <delete dir="${web.build.dir}/lib"/><br /> <copy todir="${web.build.dir}/lib" flatten="true"><br /> <fileset refid="war.dependency.fileset" /><br /> </copy><br /><br /> <!-- Create WAR --><br /> <war destfile="${war.path}" webxml="${web-inf.dir}/web.xml" manifest="${web.dir}/META-INF/MANIFEST.MF"><br /> <fileset dir="${web.dir}"><br /> <include name="**" /><br /> </fileset><br /> <classes dir="${classes.dir}"/><br /> <lib dir="${web.build.dir}/lib"/><br /> <webinf dir="${web.build.dir}"/><br /> </war><br /> </target> <br /></project></pre><br />And you can expand the build.xml for creating the EAR file similarly. Some caveats here: notice the <span style="font-weight:bold;">usescope</span> for the WAR dependencies (useScope="runtime"). This is critical to get dependencies that are only needed to be included in your WAR versus ones which are already in the App server classpath. However, the problem here is that Antlib doesn't work exactly like to the tune of the configuration specified for a jar in the Maven POM. I had to actually make a code change in the antlib source for it to behave exactly as Maven does for dependencies marked with a scope of provided as well as the optional flag in the POM file. The change is a simple one and is listed below if you want to have this behavior. Check out the source code using the information <a href="http://maven.apache.org/ant-tasks/source-repository.html">here</a>. <br /><br />The code needs to be added to the DependenciesTask.java file:<br /><pre> (line 198)<br /> for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )<br /> {<br /> Artifact artifact = (Artifact) i.next();<br /> <br /> // Added condition to recognize optional flag and filter artifacts based on useScope<br /> if (!(artifact.isOptional() && (artifact.getScope()<br /> .equals(Artifact.SCOPE_RUNTIME) || (useScope != null && useScope<br /> .equals(Artifact.SCOPE_RUNTIME)))))<br /> addArtifactToResult(localRepo, artifact, fileSet, fileList);<br /><br /> versions.add( artifact.getVersion() );<br /></pre><br />The changes I've listed above should help you migrate your application over to Maven easily when you or your organization decides to adopt Maven completely.Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-15623426714691977722009-03-14T18:12:00.006-05:002009-03-14T18:42:42.283-05:00Getting Struts 2.1 to work in Weblogic 10.3 - (contd)Updates to struts2 convention plugin as well as XWork have been committed by Musachy Barraso based on my observations to help fix Struts2 for Weblogic 10.3. I would suggest you use them. You will need to take the source code for the following classes from the trunk of their src repository:<br /><ul><br /><li>com.opensymphony.xwork2.util.finder.ClassFinder (xwork trunk)</li><br /><li>com.opensymphony.xwork2.util.UrlUtil (xwork trunk)</li><br /><li>com.opensymphony.xwork2.util.ClassLoaderUtil (xwork trunk)<br /><i>(Based on <a href="http://jira.opensymphony.com/browse/XW-672">http://jira.opensymphony.com/browse/XW-672</a>)</i><br /></li><br /><li>org.apache.struts2.convention.PackageBasedActionConfigBuilder (Struts2-struts2-convention-plugin trunk)<br /></ul><br /><i>XWork trunk(http://svn.opensymphony.com/svn/xwork/trunk)<br />Struts2 convention plugin(http://svn.apache.org/repos/asf/struts/struts2/trunk)</i><br /><br />Compile xwork first, install it into your local maven repository before compiling Struts2 convention plugin. The changes checked in will work in Struts 2.1.6 and xwork 2.1.2. While the changes will be present in subsequent versions of Struts2, there are other changes I am looking into for subsequent versions. <br /><br />Please note here that you will still need to zip the action classes into a jar (that contains a META-INF/Manifest or META-INF/somefile) for the convention plugin to pick up your action classes.<br /><br />Let me know if you have issues. <br /><br />- AmitAmithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com2tag:blogger.com,1999:blog-4785913680816428471.post-45177369280498895712009-02-22T18:23:00.009-06:002011-11-01T23:17:07.643-05:00Getting Struts 2.1 to work in Weblogic 10.3Over the last couple of days, I've been looking into the problems of running Struts2 in Weblogic 10.3. Once you wade through the errors however, the resolution is not as complicated. So, the main reason why Struts 2.1 does not work in Weblogic 10.3 (and could be earlier versions) is mainly because of the way Weblogic handles the WEB-INF classes and lib directories. The classes directory is zipped up into a jar called _wl_cls_gen.jar. Struts 2.1 specifically is looking for actions either in the classes directory or in a jar with a "META-INF/Manifest". Unfortunately, the jar created does not have the manifest and Struts2 does not know that it needs to look in a jar for the struts actions. Also, every jar within a WAR file is available as a resource via the zip file protocol, instead of a more standard jar file protocol (a really quirky implementation from BEA on this....:(, shame on them!!!).<br /><br />So then how does one go about fixing these issues? Here are the steps:<br /><ul><br /><li>You will need to add the META-INF/Manifest file into the classes directory of your WAR. This will guarantee that the _wl_cls_gen.jar is a valid jar that Struts2 will recognize.<br /></li><br /><li>You will then need to add a struts.xml to your project with the following information:<br /><constant name="struts.convention.action.includeJars" value=".*_wl_cls_gen.*"/><br />Note here that with Struts 2.1, you will be using the struts2-convention plugin, and this is an override for one of the constants that the convention plugin uses to look for actions.<br /></li><br /><li>So far, these steps were pretty easy. Now to a little bit of coding work. You will need to change a small piece of code in the convention plugin. There are 2 pieces. One piece is the change in the plugin's struts-plugin.xml. In talking with Musachy Barroso, a lead developer on Struts, this change has already been committed to the trunk. This change is to allow the convention plugin to accept the zip protocol. The change in the struts-plugin.xml is:<br /><constant name="struts.convention.action.fileProtocols" value="jar,zip" /><br /><br />The next is the following piece of code in the org.apache.struts2.convention.PackageBasedActionConfigBuilder class:<br /><br /><pre><br /> private Set<String> fileProtocols;<br /><br /> @Inject("struts.convention.action.fileProtocols")<br /> public void setFileProtocols(String fileProtocols) {<br /> if (!StringTools.isTrimmedEmpty(fileProtocols)) {<br /> this.fileProtocols = TextParseUtil.commaDelimitedStringToSet(fileProtocols);<br /> }<br /> }<br /> <br /> private UrlSet buildUrlSet() throws IOException {<br /> UrlSet urlSet = new UrlSet(getClassLoader());<br /><br /> urlSet = urlSet.exclude(ClassLoader.getSystemClassLoader().getParent());<br /> urlSet = urlSet.excludeJavaExtDirs();<br /> urlSet = urlSet.excludeJavaEndorsedDirs();<br /> urlSet = urlSet.excludeJavaHome();<br /> urlSet = urlSet.excludePaths(System.getProperty("sun.boot.class.path", ""));<br /> urlSet = urlSet.exclude(".*/JavaVM.framework/.*");<br /><br /> if (includeJars == null) {<br /> urlSet = urlSet.exclude(".*?jar(!/)?");<br /> } else {<br /> //jar urls regexes were specified<br /> List<URL> rawIncludedUrls = urlSet.getUrls();<br /> Set<URL> includeUrls = new HashSet<URL>();<br /> boolean[] patternUsed = new boolean[includeJars.length];<br /><br />//- Changed section begins<br /> for (URL url : rawIncludedUrls) {<br /> if (fileProtocols.contains(url.getProtocol())) {<br /> //it is a jar file, make sure it macthes at least a url regex<br /> for (int i = 0; i < includeJars.length; i++) {<br /> String includeJar = includeJars[i];<br /> String extUrlForm = url.toExternalForm();<br /> if (Pattern.matches(includeJar, extUrlForm)) {<br /> // If the protocol is zip, convert to jar protocol<br /> if ( extUrlForm.indexOf("zip:")!=-1 ) {<br /> String newUrl = "jar:file:/" + <br />extUrlForm.substring(4);<br /> url = new URL(newUrl);<br /> }<br /> includeUrls.add(url);<br /> patternUsed[i] = true;<br /> break;<br /> }<br /> }<br /> } else {<br /> //it is not a jar<br /> includeUrls.add(url);<br /> }<br /> }<br />//- Changed section ends<br /> if (LOG.isWarnEnabled()) {<br /> for (int i = 0; i < patternUsed.length; i++) {<br /> if (!patternUsed[i]) {<br /> LOG.warn("The includeJars pattern [#0] did not match any jars in the classpath", includeJars[i]);<br /> }<br /> }<br /> }<br /> return new UrlSet(includeUrls);<br /> }<br /><br /> return urlSet;<br /> }<br /></pre><br />The piece of code that hasn't been committed and in talking with Musachy Barroso is felt temporary is the conversion of zip protocol to jar in the buildUrlSet method. This hasn't been committed to the trunk and most likely will go in as a broader code change that will affect the XWork library that Struts2 uses.<br /></li><br /></ul><br />What I've laid out are fairly simple changes - compiling the struts2 convention plugin should be a cakewalk (maven based). I will keep this site updated as I hear more from Musachy if you are willing to wait it out before trying Struts2 in Weblogic. Let me know if you have problems getting things to work....<br /><br />- Amit<br /><blockquote><br />UPDATE: <br />The above changes are not required with Struts 2.2. Just put the following in the struts.properties file of the project.<br />#struts convention property modifications for Weblogic<br />struts.convention.action.includeJars=.*?/your-web-app-name.*?jar(!/)?<br />struts.convention.action.fileProtocols=jar,zip<br /></blockquote>Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com15tag:blogger.com,1999:blog-4785913680816428471.post-90168616890639396592009-02-18T20:51:00.004-06:002009-02-18T21:07:21.056-06:00Struts2 Annotations, Dojo and Json pluginHere's a nice way to integrate Dojo, json with the latest Struts2.1 web framework. A point to note here is that Dojo support via a plugin is deprecated in Struts2.1. My example does not use the dojo plugin, but the dojo library directly with the help of the json-plugin from the Google repository.<br /><br />My Struts2 action looks as follows:<pre><br />@ParentPackage("json-default")<br />@Namespace("/testing")<br />public class AjaxTestAction<br />{<br /> @Action( interceptorRefs={@InterceptorRef(value="json", params={"enableSMD","true"})}, <br /> results={@Result(name = "success", type="json", params={"enableSMD","true"})} )<br /> public String smd() {<br /> return "success";<br /> }<br /><br /> @SMDMethod<br /> public String sayHello(String name)<br /> {<br /> return ("Hello " + name);<br /> }<br />}</pre><br /><br />My javascript looks as follows:<pre><br /> //load dojo RPC<br /> dojo.require("dojo.rpc.JsonService");<br /> <br /> //create service object(proxy) using SMD (generated by the json result)<br /> var service = new dojo.rpc.JsonService("<%=contextPath%>/testing/ajax-test.action");<br /><br /> // execute remote service call<br /> var deferred = service.sayHello('Amit');<br /> <br /> deferred.addCallback(function(result) {<br /> alert(result.toString());<br /> });</pre><br />That's all you need. Cool eh?? One thing to note above is the url to the action - I'm using the convention plugin - but yours could look different. Have fun with Dojo. To me AJAX has never been easier. I'm not a UI guy, but my application is really looking like a RIA with Dojo toolkit and this JSON-RPC communication with the backend Java Struts2 actions.<br /><br />- AmitAmithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-47941817077508820142009-02-10T20:36:00.001-06:002009-02-24T00:06:23.952-06:00Convert a jar to an optional packageHere's the code I promised I would post to convert a jar pulled out of a Maven repository into an optional package. Note here that jars pulled out of a Maven repository have the following example syntax: examplelib-1.0.0.jar. Given this syntax, the following code manipulates the Manifest of the jar to make the jar compatible with the JEE optional package specifications:<pre><br /> ZipFile oldZipFile = new ZipFile(new File(fileName));<br /> Enumeration<? extends ZipEntry> entries = oldZipFile.entries();<br /><br /> ZipOutputStream out = new ZipOutputStream(new FileOutputStream(<br /> outFile));<br /> <br /> // Loop through entries in the existing jar file <br /> while (entries.hasMoreElements())<br /> {<br /> ZipEntry entry = entries.nextElement();<br /> // Put all other files besides the manifest into the converted jar as is<br /> if (entry.getName().indexOf("MANIFEST") == -1)<br /> {<br /> out.putNextEntry(entry);<br /><br /> InputStream inStream = oldZipFile.getInputStream(entry);<br /> // Transfer bytes from the ZIP file to the output file<br /> byte[] buf = new byte[1024];<br /> int len;<br /> while ((len = inStream.read(buf)) > 0)<br /> out.write(buf, 0, len);<br /><br /> inStream.close();<br /> } <br /> else<br /> {<br /> manifest = new OptManifest();<br /> manifest.setExtName(trueFileName);<br /> <br /> // Read the manifest<br /> InputStream inStream = oldZipFile.getInputStream(entry);<br /> BufferedReader in = new BufferedReader(<br /> new InputStreamReader(inStream));<br /> StringBuffer buffer = new StringBuffer();<br /><br /> // Read each line of the manifest file to determine its state<br /> boolean extnNameFound = false;<br /> boolean specVerFound = false;<br /> boolean implVerFound = false;<br /> <br /> String line = null;<br /> while ((line = in.readLine()) != null)<br /> {<br /> if ( !specVerFound )<br /> specVerFound = ( line.toLowerCase().indexOf("specification-version")!=-1? true: false ); <br /><br /> if ( !implVerFound )<br /> implVerFound = ( line.toLowerCase().indexOf("implementation-version")!=-1? true: false ); <br /> <br /> if ( !extnNameFound )<br /> extnNameFound = (line.toLowerCase().indexOf("extension-name")!=-1? true: false);<br /> <br /> boolean hasOptPkgParam = ( specVerFound || implVerFound || extnNameFound? true : false );<br /> <br /> // Add lines that are not optional package parameters<br /> if ( line!=null && !line.equals("") && !hasOptPkgParam )<br /> buffer.append(line + "\n");<br /> }<br /> <br /> // Add Optional package information to the manifest<br /> String versionToUse = determineVersion(fileName);<br /> if ( versionToUse!=null && !versionToUse.equals("") )<br /> {<br /> // Assign cleaned up specification version <br /> String specVersionToUse = getSpecificationVersion(versionToUse); <br /> buffer.append("Specification-Version: " + specVersionToUse + "\n");<br /> manifest.setExtSpecVersion(specVersionToUse);<br /> <br /> // Assign cleaned up implementation version<br /> String implVersionToUse = getImplementationVersion(versionToUse);<br /> buffer.append("Implementation-Version: " + implVersionToUse + "\n");<br /> manifest.setExtImplVersion(implVersionToUse);<br /> } <br /> <br /> inStream.close();<br /> in.close();<br /><br /> ZipEntry newManifestEntry = new ZipEntry(entry.getName());<br /> out.putNextEntry(newManifestEntry);<br /><br /> // Transfer bytes from the file to the ZIP file<br /> out.write(buffer.toString().getBytes());<br /> }<br /><br /> // Close the new entry in the new zip file<br /> out.closeEntry();<br /> }<br /> out.close();<br /><br /><br /></pre>Here's how your can derive the specification and implementation versions:<pre><br /> private String getSpecificationVersion(String versionToUse)<br /> {<br /> StringBuffer specVersionToUse = new StringBuffer();<br /> // Regex expression that only allows digits and periods, and a digit cannot<br /> // be preceded by an underscore<br /> String regex = "(?<!_| )[\\.?[0-9]*]";<br /> Pattern pattern = Pattern.compile(regex);<br /> Matcher m = pattern.matcher(versionToUse);<br /> while ( m.find() )<br /> specVersionToUse.append(m.group());<br /> <br /> if ( specVersionToUse.charAt(0)=='.')<br /> specVersionToUse = specVersionToUse.replace(0, 1, "");<br /> <br /> if ( specVersionToUse.charAt(specVersionToUse.length()-1)=='.')<br /> specVersionToUse = specVersionToUse.replace(specVersionToUse.length()-1, specVersionToUse.length(), "");<br /><br /> return specVersionToUse.toString();<br /> }</pre><pre><br /> private String getImplementationVersion(String versionToUse)<br /> {<br /> String implVersion = versionToUse;<br /> int versionIndex = versionToUse.indexOf('-');<br /> <br /> // Get the version starting from the hyphen prior to a digit<br /> String regexPattern = "[0-9]";<br /> while ( versionIndex!=-1 )<br /> {<br /> char charAtIndex = versionToUse.charAt(versionIndex+1); <br /> if ( !Pattern.matches(regexPattern, String.valueOf(charAtIndex)) )<br /> versionIndex = versionToUse.indexOf('-', versionIndex+1);<br /> else<br /> {<br /> implVersion = versionToUse.substring(versionIndex+1);<br /> break;<br /> }<br /> }<br /> return implVersion;<br /> }</pre>Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-28743745333050262412009-01-25T02:50:00.002-06:002009-03-14T19:08:08.951-05:00A Tabbed Console for WindowsOk, I forgot to mention one thing - there's a cool little open source project called Console (<a href="http://sourceforge.net/projects/console">http://sourceforge.net/projects/console</a>) that you just have to start using. Get the 2.0 development version - its pretty far along that you can use it without any major glitches. This little thing lets you create a tabbed Windows command shell or for that matter even a tabbed cygwin or powershell. Its free.....so what are you waiting for. Get it now, along with notepad++(<a href="http://notepad-plus.sourceforge.net/uk/site.htm">http://notepad-plus.sourceforge.net/uk/site.htm</a>) if you didn't know about that either.....:) <br /><br />For example you could load multiple cygwin windows as shown here by pointing to the cygwin.bat file - <br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuZsz90UsvomgELEnUspRj2T1v9ZhldP-L0_i4zkWxX7D_-Bjosv6BLFHjrI0DwjXmLO-SsnoABlVJ97dzcH2mvgEVF0aR9Xa2iO6KBonsv0ofufT2f8342oBkroalWq3rJMnISu5Vck-R/s1600-h/console2-settings.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 269px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuZsz90UsvomgELEnUspRj2T1v9ZhldP-L0_i4zkWxX7D_-Bjosv6BLFHjrI0DwjXmLO-SsnoABlVJ97dzcH2mvgEVF0aR9Xa2iO6KBonsv0ofufT2f8342oBkroalWq3rJMnISu5Vck-R/s320/console2-settings.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5313198541584587538" /></a><br /><br />Once you have cygwin setup, you could create tabs that spawn off an ssh shell to a server by creating a cygwin modified batch file for connection to that server - <br />(Example contents of this script)<br />eg: <pre>@echo off<br />C:<br />chdir C:\cygwin\bin<br />bash --login -i -c "export DISPLAY=localhost:0.0; ssh -X myuserid@remotesvrname"<br /></pre><br />- AmitAmithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-58421381472932765182009-01-15T02:13:00.000-06:002009-02-18T21:08:09.153-06:00Recommendations for hard economic timesIts been a while since I've blogged, partly because I've been busy on a JEE project with a pretty extensive scope. Lots of new technologies in use and its interesting to see how the Java enterprise landscape is shaping up with JEE 5 containers now getting adopted for mission critical systems in the enterprise. Here are a couple of observations worth mentioning:<br /><br />While most people know more about the EJB3 features, very little has been mentioned about optional packages and their use. I've blogged about this before, and as I've seen on my project, optional packages is a worthwhile addition in JEE 5. Only problem here is the conversion of regular libraries to optional packages and I wrote code to automate that which I will post here soon.<br /><br />Spring 2.5 with annotation support opens up all kinds of possibilities. I didn't like Spring before, but if you extend their annotation framework, sky's the limit to what you can do - like you could create your own code to inject service handles where the service protocol could be proprietary and not just RMI/IIOP as is the case with EJBs. Example would be some legacy services which you want to code to today, but maybe want to convert to EJBs down the line. In such a scenario, one could easily write a dynamic proxy and use Spring to inject it into say a Struts2 action or an EJB. Essentially here, you are converting a legacy service to have an interface that very well could look like an EJB interface and then providing ways to marshal data from the legacy service into Java objects in the dynamic proxy class.<br /><br />Struts2 is maturing well and its overall quick adoption is making it the framework of choice again for web development ( besides JBoss Seam maybe ). <br /><br />XStream is a really slick STAX xml parser that makes marshaling XML real easy and real fast to POJO objects. With a couple of tweaks to this library (which I'll post later), you can literally forget about the xml parsing piece in your app.<br /><br />Finally, if your system requires a distributed caching mechanism, <a href="http://www.terracotta.org">Terracotta</a> may be a worthwhile addition to your enterprise suite. They have lots of good information on their site, and plenty of flexibility in implementation. However, they don't have a good implementation for Web Session offloading even though they state otherwise. Essentially, they support offloading web sessions only if your application doesn't have resources/pages secured via roles (which I just can't see any sense in - aren't all well architected apps in the enterprise secured by roles that limit access to information or pages based on the end user's role). Anyway, its still a great product for distributed caching even without the the web session offloading.<br /><br />So I end my technology update here for now. Even though the times are hard, technologies abound and it maybe a worthwhile exercise to do your research on these new technologies. If you want to be adventurous, start learning a new language - the one I'm getting my feet wet in is Objective C. It would be useful skill incase your company decides to write an app for the iPhone. If you don't have a Mac (you can invest in it as the times start getting better), then you can play around with Obj C using <a href="http://www.gnustep.org/">GNUStep</a>. I'm surprised Obj C doesn't get enough of a mention, because its a dynamic language as well. <br /><br />Start preparing for better days ahead...<br /><br />- AmitAmithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-50991738941400704302008-09-27T15:16:00.011-05:002009-02-24T00:06:48.443-06:00Building enterprise applications with Maven to use optional packages<div align="justify"><br />The Java 1.3 feature of <a href="http://java.sun.com/j2se/1.4.2/docs/guide/extensions/versioning.html">optional packages</a> introduced support for an expanded set of Jar-file manifest attributes that enable an application jar to specify its list of dependencies on other jars. Maven can generate a jar and build a manifest automatically for you so that you can leverage optional packages deployed in your environment (whether it be the classpath or jars deployed in an application container). If you are looking to build and deploy an application EAR that has dependencies on a slew of 3rd party libraries, you can deploy the 3rd party libraries as optional packages and cut down on the size of your EAR file across many applications. The reuse of these 3rd party jars across multiple Web or enterprise application deployments becomes really handy if you want all these applications to do a common upgrade to a different version for their dependent library. So how do you tell Maven to do this? Here's an example of a Web application POM file. Within the <span style="font-weight: bold;">build </span>section, specify the following snippet -<br /><pre><br /> <plugins><br /> <plugin><br /> <artifactId>maven-war-plugin</artifactId><br /> <configuration><br /> <archive><br /> <manifest><br /> <addExtensions>true</addExtensions><br /> </manifest><br /> </archive><br /> </configuration> <br /> </plugin><br /> </plugins><br /></pre><br /><br />However, while building this WAR file, the dependencies will still get pulled in unless you specify another attribute on your dependencies. Example here - if you have a dependency on aspectj and aspectj is deployed to your container, say Weblogic10, as an optional package, then in your POM for your WAR file, you would specify the following - <br /><pre><br /> <dependency><br /> <groupId>org.aspectj</groupId><br /> <artifactId>aspectjrt</artifactId><br /> <version>1.6.0</version><br /> <!-- <scope>provided</scope> --><br /> <optional>true</optional><br /> </dependency><br /></pre><br />The attribute that's important in this snippet is the "optional" attribute, the presence of which will omit the file from being included in the WAR file. The omission of the file is not the only thing that is important here. The "scope" element is also important. There are some specific rules that Maven follows when generating the manifest based on the "scope" and "optional" tags that you need to understand. Here's their <a href="http://docs.codehaus.org/display/MAVENUSER/Dependency+Scopes">docs</a> that shows a table that helps clearly explain the relationship between these 2 attributes. In the above example, while the optional element will will exclude the jar from being added to the WAR file, the scope element will also cause the jar's extension name to be omitted from the MANIFEST - something you probably do not want if you are looking to leverage optional packages deployed. <br /><br />A jar file deployed as an optional package essentially needs to have 3 properties in its manifest file - <br /><pre><br /> Extension-Name: asjpectj<br /> Specification-Version: 1.6.0<br /> Implementation-Version: 1.6.0<br /></pre><br />The manifest file built by Maven will put the extension name of the dependent jar in the "Extension-List" property of the manifest of your WAR file. It will also put the implementation version. You have to make sure that both these attributes match with those of the deployed optional package (i.e. in this example the aspectj jar). Otherwise, you'll probably get a <span style="font-style:italic;">ClassNotFoundException</span>. As long as you get the extension name and implementation version of the optional package the same as what Maven generates in the manifest of the dependent WAR, everything will work and deploy without a problem. Take a look at this <a href="http://edocs.bea.com/wls/docs100/programming/libraries.html#libmanifest">article</a> for Weblogic to understand the constraints on naming for optional packages.<br /><br />While the above is tedious at first, it becomes a very efficient way of managing application dependencies in enterprise production systems once you get everything working and lined up. I actually created a Swing tool that takes an EAR file that has all the dependencies in it and spits out the jars converted into optional packages that Maven understands. All you really have to do is take the version information from the name of the jar and put it into the Specification(as long as this contains only digits eg. "1.1.2" ) and implementation properties of the jar's manifest.<br /><br />Though your initial effort to get everything setup will take a little bit of time, it will be well worth it. So give this operational efficiency a try.....<br /></div>Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-19411857041949900782008-08-07T21:07:00.020-05:002008-08-16T15:41:08.362-05:00Using Ubuntu for Java development in the enterprise<div align="justify"><br />Ubuntu's been a rage over the last 2-3 years, however it definately seems to be catching on with a lot of folks as a possible OS of choice, with the widespread dissatisfaction around MS Vista. I decided to really give Ubuntu the spin to see if I really would develop applications and do my daily work in that environment - it's one thing saying Ubuntu's an alternative to Windows, its another to actually get the tools for the job working on this OS.<br /><br />So first thing I did was to install Ubuntu using <a href="http://wubi-installer.org/">Wubi</a> from within Windows Xp. This to me is a really cool piece of software, as Ubuntu looks like any other Windows program installed. However, it actually allows Ubuntu to be booted when your pc's turned on by adding an entry to the Windows boot menu. Ubuntu is installed within a file in the Windows file system (c:\ubuntu\disks\root.disk), this file is seen by Linux as a real hard disk. The install didn't take too much time, about 20 minutes on my Toshiba M700. So essentially, you're not running Ubuntu in a virtualized mode.<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWPeZDqQRAuVoIXYBoB8pXfKTDpfk7vd-5CMqI5qQtvNf-fn7S6vBYVYZ6lCLI4GYF8xIQqtBEM1OCEsI00FJ9Kv1f0JJ1jVxmMw-f7NlgXPlk1hRKdZ2Xqw9ZSqq0rle-hrSN8aPG2CZO/s1600-h/Screenshot.png"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWPeZDqQRAuVoIXYBoB8pXfKTDpfk7vd-5CMqI5qQtvNf-fn7S6vBYVYZ6lCLI4GYF8xIQqtBEM1OCEsI00FJ9Kv1f0JJ1jVxmMw-f7NlgXPlk1hRKdZ2Xqw9ZSqq0rle-hrSN8aPG2CZO/s320/Screenshot.png" alt="" id="BLOGGER_PHOTO_ID_5232777388849098418" border="0" /></a><br />While Ubuntu looks pretty good, the UI doesn't necessarily looks extraordinary. So I decided to jazz it up to look like the MacOS X. Take a look at <a href="http://maketecheasier.com/turn-your-ubuntu-hardy-to-mac-osx-leopard/2008/07/23/">this</a>. On the left, that's what my desktop looks like now.<br /><br />So now that I had the system look spiffy, I decided to do some real Java work on it. With Synaptic software manager, I installed JDK 1.5. I also downloaded MyEclipse 6.5. Now for the application server, I decided to use Weblogic - one of the more common enterprise wide application servers in use in production environments. I downloaded the RedHat version of Weblogic 10 MP1. For the database, MySQL was the obvious choice and Synaptics makes that an easy install.<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZgWh2BJdlCqulsIv9KuoiuCeRXZup1oSt09neCpSJio51o0IEwWM1xMseZjI0tdwcZLvnKA9U4pxsN8zY8hp9G5CLH1EAQVxdVvwIpO0jbX3IlMEfmdIztvyQcNlTPGcETpfZaQpHGTOS/s1600-h/Screenshot.png"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZgWh2BJdlCqulsIv9KuoiuCeRXZup1oSt09neCpSJio51o0IEwWM1xMseZjI0tdwcZLvnKA9U4pxsN8zY8hp9G5CLH1EAQVxdVvwIpO0jbX3IlMEfmdIztvyQcNlTPGcETpfZaQpHGTOS/s320/Screenshot.png" alt="" id="BLOGGER_PHOTO_ID_5232782675476762114" border="0" /></a><br />Finally, after all that, I got a JEE5 application deployed and running for a quick test of all components. Everything worked perfectly - infact, Weblogic actually seems to run faster than it does on the Windows side - under the same hardware. On the whole, I also saw that the OS was consuming lesser memory helping programs overall. Ubuntu seems a really viable option for Java developers, and I would definitely recommend that you give some thought to this option, especially in your organization if you're a pure Java shop - lesser cost to maintain, and closer to your production environments. MS applications like Office have substitutes (OpenOffice, Evolution), but you can also use virtualization software to run these MS apps seamlessly on Ubuntu using something like <a href="https://help.ubuntu.com/community/WindowsXPUnderQemuHowTo">QEmu</a>. I really do think this has the potential to take off in many organizations.<br /><br />PS: While I initially posted information about a 32bit Ubuntu install, I later went on and installed the 64bit version since my laptop has Intel Core2 chips. I was able to run all software I mentioned above and mostly also saw some performance improvement. The only glitch was that 2 of the MacOS options - the global menu and startup screens don't work or need to be compiled for a 64bit system. On the software side, Acrobat Reader couldn't be installed, however Ubuntu has pdf-reader preinstalled - so that's not something you'll miss.<br /></div>Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-13053219964020610122008-07-17T21:49:00.018-05:002008-07-18T00:04:12.727-05:00Eclipse and Maven integration<div align="justify">If you are looking to use Maven on your next Project and currently use Eclipse as your IDE, then I would suggest you also take a look at MyEclipse 6.5. This new version of MyEclipse has some nifty features implemented that aren't just a whole bunch of open source plugins bundled together (like prior versions of Myeclipse) - especially the integration built in for Maven. <br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2qG9UgpCTPfMPOJUbWWadlf0wePQTPdsKpGKb2ZBPGyIsNUMmGUis1POS_-h6moc9tyBE0Fxvv426GY1o3AUMC0CvYcJz8ai4JjAKyfUsVKwSg5Cj0ygy88ASvda2pyYFZpMoGi8ymojH/s1600-h/maven-projects.jpg"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2qG9UgpCTPfMPOJUbWWadlf0wePQTPdsKpGKb2ZBPGyIsNUMmGUis1POS_-h6moc9tyBE0Fxvv426GY1o3AUMC0CvYcJz8ai4JjAKyfUsVKwSg5Cj0ygy88ASvda2pyYFZpMoGi8ymojH/s320/maven-projects.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5224195181654761106" /></a><br />Myeclipse 6.5 is built on Eclipse 3.3 and the Web Tools Project(WTP). The Maven support I am referring to isn't available in the regular Maven IDE plugin. What has been provided with MyEclipse is the ability to create EJB and WEB projects structured around Maven. These EJB/WEB projects are enabled to be deployable to your application server of choice from within the IDE. While this makes life easy for a developer, one still needs to understand a little bit more about how to go about structuring these EJB and WEB projects to create the necessary enterprise artifact or EAR file. <br />Using the MyEclipse project options, I went ahead and created two projects - FrmkConsoleServices, an EJB project and FrmkWebConsole, a WEB project. Due to the lact of support for creating an Enterprise project (essentially one that creates the EAR file), I created the project - FrmkConsole, that brings together the other two projects or creates the EAR file containing a JAR and WAR. The POM for this EAR project looks like this, which I had to hand-code since MyEclipse does not have a capability to create such an Enterprise project (a feature they need to have in their next version asap ):<br /><pre><br /> <dependencies><br /> <dependency><br /> <groupId>com.mycompany.myappfrmk.console</groupId><br /> <artifactId>console-svcs</artifactId><br /> <type>ejb</type><br /> <version>1.0</version><br /> </dependency><br /> <dependency><br /> <groupId>com.mycompany.myappfrmk.console</groupId><br /> <artifactId>web-console</artifactId><br /> <type>war</type><br /> <version>1.0</version><br /> </dependency><br /> </dependencies><br /> <build><br /> <plugins><br /> <plugin><br /> <groupId>org.apache.maven.plugins</groupId><br /> <artifactId>maven-ear-plugin</artifactId><br /> <version>2.3.1</version><br /> <configuration><br /> <generateApplicationXml><br /> true<br /> </generateApplicationXml><br /> <generatedDescriptorLocation><br /> ${basedir}/target<br /> </generatedDescriptorLocation><br /> <finalName>FrmkConsole</finalName><br /> </configuration><br /> </plugin><br /></pre><br />You will also need to control the creation of the various project artifacts, or get the WAR,JAR built before the EAR, and that's the reason for creating FrmkConsoleRoot. It essentially specifies the modules that make up the project and the POM really only contains the following, besides declaring the packaging for it to be of type "pom":<br /><pre><br /> <modules><br /> <module>../FrmkConsoleServices</module><br /> <module>../FrmkWebConsole</module><br /> <module>../FrmkConsole</module><br /> </modules><br /></pre><br />Overall though, I was not particularly happy that I had to create 4 top-level projects for me to create an EAR file. This approach may work for groups of developers working separately on the WEB and Service layer, however the ideal structure here should be one top-level project that has multiple modules under it - in this case 3 (the ear, the war, the jar). If you don't want to use MyEclipse, then I would go with the <a href="http://m2eclipse.sonatype.org/index.html">m2eclipse</a> plugin. This is pretty good and allows you to create projects based on archetypes available. For example an archetype that helps in building a EAR file is "maven-archetype-j2ee-simple". Using m2eclipse, you can select this archetype by building a new Maven project and selecting the "internal" catalog that has these predefined template projects. You essentially want your project structured according to this archetype.At command line you can retrieve it using the following command:<br /><pre>mvn archetype:create -DgroupId=com.mycompany.myapp -DartifactId=my-webapp <br />-DarchetypeArtifactId=maven-archetype-j2ee-simple -DarchetypeVersion=1.0</pre><br />Well, one thing I can say after all that - its not easy to find this information, but at-least its getting there. Once you have your first project setup, subsequent ones should be easy with Maven. Those of you who are used to ant may find all this a little cumbersome initially, but Maven's archetype is exactly what <span style="font-weight:bold;"><span style="font-style:italic;">convention over configuration</span></span> is all about. Give Maven a try, its not all bad....:).<br /></div>Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-62491228246760097482008-07-10T14:57:00.013-05:002008-07-18T00:05:29.506-05:00Modeling Services using a tool<div align="justify"><br />If you are looking to do SOA modeling, I would recommend using <a href="http://staruml.sourceforge.net/en/">StarUML</a>. I think this is an awesome piece of open source software for doing UML based modeling. Its comparable to the likes of IBM's Rational tools for Object Modeling using UML notations. However, the thing I found interesting was the flexibility it offered me to tweak the tool to add another modeling profile - a service modeling profile, that I thought would be a good start in creating a "Service architecture map" in line with the methodology, Steve Jones (CTO, Capgemini) talks about for service discovery. That methodology has been contributed to OASIS and you can read about that methodology <a href="http://www.oasis-open.org/committees/download.php/15071/A%20methodology%20for%20Service%20Architectures%201%202%204%20-%20OASIS%20Contribution.pdf">here</a>.<br /><br />If you go with that approach, the template I created for StarUML, should help you create the Service architecture map for your organization. That template can be downloaded here (<a href="http://amitdk2015.googlepages.com/staruml-soa.zip">Services Modeling template for StarUML</a>). Unzip this zipfile into the modules directory of your StarUML install. When you start StarUML, you should see a new option in the "New Project By Approach" dialog called - "Service Modeling Approach". An example diagram using this template would look like this:<br /></div><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjha8Y2V6NxH3dY1qnbHEXC1dOmL8AFvPozskvSPwfmXjSnszneGGEM_4emagU0W_6OG2nX8vRcrc2oU5qeWKasF2Wtbv01bT7-QmZ7nBNwvz-bvvGNaBNawRHaENl_tIhJTwBawjmVgGJF/s1600-h/service-example.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjha8Y2V6NxH3dY1qnbHEXC1dOmL8AFvPozskvSPwfmXjSnszneGGEM_4emagU0W_6OG2nX8vRcrc2oU5qeWKasF2Wtbv01bT7-QmZ7nBNwvz-bvvGNaBNawRHaENl_tIhJTwBawjmVgGJF/s320/service-example.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5221625493189981202" /></a><br />You can further extend this template if you wished - the documentation for StarUML is <a href="http://staruml.sourceforge.net/docs/developer-guide(en)/toc.html">here</a>Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-60331300406400072572008-06-30T22:02:00.021-05:002008-07-18T00:05:56.457-05:00Using custom spring annotations in the Web and App tierI had blogged <a href="http://tech-architecture.blogspot.com/2008/04/liking-spring-25-love-annotations.html">earlier</a> about why I thought Spring 2.5 annotations were really cool and well implemented. I had mentioned in that article how one could use one's own custom annotations through Spring 2.5 to inject dependencies into web application classes as well as the EJBs in the application tier. I went ahead and tried this out for the web and app tier to see how challenging this really was. It required the web classes that had my custom annotations to be instantiated through Spring. The Struts2 framework that's really getting a lot of momentum these days (check out Matt Raible's stats on this <a href="http://raibledesigns.com/rd/entry/re_which_is_the_hottest">here</a>) integrates well with Spring and though the documentation is not thorough, the link <a href="http://struts.apache.org/2.x/docs/spring-plugin.html">here</a> gives a fairly good idea of how one goes about Spring enabling struts2. The gist here is that the object factory for all struts actions is the StrutsSpringObjectFactory. The configuration of my web.xml really needed only this listener:<br /><br /><pre> <listener><br /> <listener-class><br /> org.springframework.web.context.ContextLoaderListener<br /> </listener-class><br /> </listener></pre><br />I also had an applicationContext.xml (under WEB-INF) that scanned for my own custom annotations. So that allowed my Action classes to use my custom annotations. With Struts2's native annotations, you don't need to worry about the struts-config.xml for result-jsp mappings either. Its all there in your action class. I even had advice around the action to capture timing stats thus implementing "seperation of concerns" to the hilt!! Well that took care of the web tier.<br /><br />My app tier was EJB 3.0 based and I found that Spring had an interceptor that helped my cause. So my session facade had to be annotated with my custom Spring interceptor as shown here:<br /><br />@Stateless(name = "HelloWorldService")<br />@Interceptors(MySpringBeanAutowiringInterceptor.class)<br />public class HelloWorldService implements HelloWorld, Serializable<br /><br />The custom Spring interceptor essentially helps me to use a custom annotation (my own type for autowiring) in the EJB. The code for the interceptor looks like:<br /><pre><br />public class MySpringBeanAutowiringInterceptor extends SpringBeanAutowiringInterceptor<br />{<br /> @Override<br /> protected void configureBeanPostProcessor(AutowiredAnnotationBeanPostProcessor processor, Object target) {<br /> processor.setAutowiredAnnotationType(CustomAutowiring.class);<br /> }<br />}<br /></pre><br />Now here came the tricky part - I had to create the beanRefContext.xml for Spring and had to have it load up another context file that had information to setup Spring to search for my custom annotations as so -<br /><pre><br /> <bean class="org.springframework.context.support.ClassPathXmlApplicationContext"><br /> <constructor-arg type="java.lang.String" value="ejbApplicationContext.xml"/><br /> </bean><br /></pre><br />In the ejbApplicationContext.xml, I setup the component-scan tag to search for my annotations. This worked though I was initially at a loss as to why I need to specify two context files to get dependencies to be injected by Spring. I found the reason for this on the Spring forums (by Juergen Hoeller) - <br /><br /><blockquote><div align="justify">Essentially, your "beanRefContext.xml" file will typically define a ClassPathXmlApplicationContext which in turns loads your actual beans. The "beanRefContext.xml" mechanism allows multiple such shared ApplicationContexts to co-exist, differentiated by bean factory locators. In the default EJB3 case, simply define one such ApplicationContext which will be picked up automatically, regardless of name.</div></blockquote> <br />You can also read more on this in the Spring docs <a href="http://static.springframework.org/spring/docs/2.5.x/reference/ejb.html">here</a>. The other thing also was that I had to make sure I had the correct set of libraries in my EAR. Those libraries were:<br /><br />- spring.jar<br />- asm-2.2.3.jar<br />- asm-commons-2.2.3.jar<br />- aspectjrt.jar<br />- aspectjweaver.jar<br />- common-annotations.jar<br />- commons-logging.jar<br />- log4j-1.2.14.jar<br /><br />Overall, I found that the web side Struts2 integration with Spring seemed much more cleaner that the EJB one. At this point I would still recommend this approach, but make sure you have a little bit of time on your hands to get this working exactly the way you want it. If you are interested, I can further share any other information - just call out.<br /><br />I will continue to tweak and research on the EJB implementation - but overall, this approach still makes for an interesting application design.Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com1tag:blogger.com,1999:blog-4785913680816428471.post-24780260354657867812008-06-08T23:51:00.007-05:002008-07-18T00:06:43.901-05:00Microsoft TechEd 2008: Oslo and WCF<div align="justify">This was the first time that I attended a Microsoft TechEd event. While the sessions were interesting, there was a lot of emphasis on WCF ( Windows Communication Foundation ), and understandably so I guess - its essentially a platform(WCF extensions) on a platform (.NET) and I say that because of the swooping changes that are brought to the .NET platform by adding the WCF implementation to it. At the core, WCF implements WS-* standards for web services, however there are very few vendors (if any other) that have implemented WS-* to this degree and simplicity. I think that right there should be a wakeup call for Java folks. I was pretty impressed with what I saw of WCF and look forward to playing with it.<br /><br />Microsoft's codename "Oslo" project could also potentially be another knee-jerker for the Java camp. "Oslo" sounds interesting as a concept and is essentially a broad set of innovations touching many aspects of the application lifecycle, including languages, development tools, integration, application management, and more. The whole concept of "Oslo" is based around models. One would jump to the conclusion that this is Microsoft's MDD (Model Driven Design) methodology. However, its not really that. "Oslo" consists of 3 parts : Repository, Lifecycle manager, and schema language. The repository maintains the various model artifacts, and so models in the case of "Oslo" are anything in IT that has a representation through the schema and is maintained in the repository (eg. things like applications, computers, processes, services,SLAs). The schema extensions help to formalize definitions of basic entities (infrastructure and business based) in a software's life-cycle. What is really cool is the lifecycle manager uses the repository and the schema extensions to manage the entities represented. So for example, if a component is deployed on a certain platform/environment, on multiple machines, lifecycle manager will know about this profile and deploy the component accordingly onto the defined platform/environment.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkjoE9BwQnfQYhQed9zo4aYpPrUI7KYfz3jS3gi27WHSE3ppeEjiXyz907cnZdh-nEID0qWDvW7u9xk2WRrNOj0y8VeyUyVwQj637tNPuxkBc0HyhyphenhyphenMEeJSSRAYk3y-o4DFl_O2Q0rLPgi/s1600-h/oslo.jpg"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkjoE9BwQnfQYhQed9zo4aYpPrUI7KYfz3jS3gi27WHSE3ppeEjiXyz907cnZdh-nEID0qWDvW7u9xk2WRrNOj0y8VeyUyVwQj637tNPuxkBc0HyhyphenhyphenMEeJSSRAYk3y-o4DFl_O2Q0rLPgi/s320/oslo.jpg" alt="" id="BLOGGER_PHOTO_ID_5210497493903273586" border="0" /></a>All this occurs through sophisticated visual integration with tools like Visual Studio, Visio and Oslo's own visual editor - as a way to provide the same information to tools that people typically use in different roles ( analyst, developer etc). So Oslo really seems to me like a tool from the software development lifecycle perspective - modeling a component/service/process, building it, and then moving it and deploying it to an environment.<br /><br />The key here is that there are so many bits and pieces to this colossal, that only a company like Microsoft could pull this feat through - the Open space world will probably have a hard time replicating such an effort and collaborate effectively. That would invariably give Microsoft a competitive edge. Another scary thought for the Java folks.<br /><br />From what I saw at TechEd, Microsoft has some interesting technologies that have a lot of potential. C# as a language is evolving better and more rapidly than Java and so is the declarative language F# over something like Groovy on the Java side. In a services world too, WCF's ease of use and WS-* richness also place Microsoft very well in that space. "Oslo" still is a mystery, but if it comes close to what Microsoft is talking about, I think the Java space could find itself in troubled waters very soon :(.<br /></div>Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-85059741686221219252008-05-12T22:45:00.010-05:002008-07-18T14:42:47.882-05:00A Single Sign-on implementationIf you are looking to implement a Single Signon implementation, then a worthwhile library to look at would be OpenSAML 2.0. The 2.0 library is well written and much more intuitive to use compared to its predecessor - OpenSAML 1.0. I recently implemented a SAML 1.1 solution using the 2.0 library on Weblogic 8.1. The library by default is for the Java 1.5 platform, however using Retroweaver, one can use it for Java 1.4 (since Weblogic 8.1 does not work with Java 1.5). The SAML Browser/Artifact profile is pretty easy to understand and implement with the library and good ol' Wikipedia gives an easy explanation of <a href="http://en.wikipedia.org/wiki/SAML_1.1">the steps</a> needed to get the communication going. However, I would recommend that you read through the OASIS <a href="http://www.oasis-open.org/committees/download.php/3405/oasis-sstc-saml-bindings-1.1.pdf">SAMLBind</a> document to get a better understanding of implementation details.<br /><br />I used Xfire (v1.2.6) to implement the <b> </b>Artifact Resolution Service at the IdP<b> </b>that the Service provider invokes once it receives the artifact posted to it. Since the OpenSAML library works with the raw xml document, one needs to configure xfire to prevent marshalling of the incoming xml to java POJOs. XFire has a cool way to work with raw xml documents, using a binding called as <span style="font-style: italic;"><a href="http://docs.codehaus.org/display/XFIRE/Message+Binding">Message Binding</a>.</span> So the xfire service interface looks like:<br /><blockquote>public XMLStreamReader invoke(Document samlRequest) throws Exception</blockquote>and the OpenSAML library can then work with the DOM document using the <span style="font-style: italic;">XMLObjectBuilderFactory</span> request factory.<br /><br />Some quirks here - while returning the response, I had to return an object of type XMLStreamReader - I used W3CDOMStreamReader to convert to this type. Also, for getting SOAP faults correctly, the interface definition of the service had to throw the base "Exception"class and not a specific exception type.<br /><br />While the implementation does add a bit of added complexity through the use of XFire, it works out pretty well and allows one to use these excellent libraries -XFire & OpenSAML 2.0 - together to leverage the best of both.<br /><br />The solution is on its way into production this week - fingers crossed....:).Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-81794143858797526512008-04-30T23:34:00.009-05:002008-07-18T00:07:50.065-05:00SOA - how does one discover services??Lately in the SOA yahoo group, I was involved in a discussion about what one would consider a successful SOA implementation. Given that SOA really has to be considered from a business perspective, there are very few case studies out there that provide details about the business specifics of implementation. These case studies only talk about the integration of various systems. Very disappointing and frustrating for people to learn from.<br /><br />A successful implementation of Business SOA really has to outline and give details about the process of service discovery (business services more specifically) and how an organization goes about outlining the Service architecture map that helps it to zoom in on those services that provide strategic /tactical advantage versus ones that are more utility services and could probably be bought. KPIs around these business services would then help the organization measure the benefits of these business services in the strictest sense in line with its strategies.<br /><br />So, as I research on SOA, those interesting case studies elude me - however the best source of material I've come across has been from Steve Jones (CTO, CapGemini). In general though, service discovery comes very close to the methodology of discovering domain objects in an enterprise wide system. As Steve has eloquently put - <span style="font-style: italic;">services tend to be around functional nouns, so "Order Management" is a good example, it will have capabilities that are the verbs "newOrder","createDispatch", etc and it will have priorities for its operation e.g. availability, response times, dispatch sizes etc</span>.<br /><p>It definitely seems like OO design, however this discovery has to be top-down, with business folks heavily involved throughout service discovery. Most organizations struggle with that, but maybe there's light at the end of the tunnel as the industry gets a better understanding and feel for SOA and what such undertakings really require an organization to do.<br /></p>Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-69422009535870741442008-04-24T23:07:00.007-05:002008-08-15T01:15:23.740-05:00Liking Spring 2.5 (love annotations)Ok, I think I feel comfortable in adopting or suggesting the Spring framework for JEE projects. And I am sure some people would say that they had reached that conclusion a long time ago. However, earlier I would tend to disagree on a couple of counts if someone suggested that Spring was the best thing to happen to Java and a better alternative to the existing JEE spec. The things I despised about Spring earlier were:<br /><ul><li>Too many libraries to include</li><li>Too much in an Xml configuration leading to some tricky runtime debugging errors</li></ul>However, the Spring folks seem to have taken notice and have addressed these problems with Spring 2.5. So at my first opportunity, I decided to code with Spring 2.5 leveraging it mainly for its annotation facility. A really good resource I found for seeing the customization of Spring's annotation features is on <a href="http://www.infoq.com/articles/spring-2.5-part-1">InfoQ</a>. However, I also extended a couple of the classes in Spring to be able to mimic resource manager injection capability (aka autowiring), similar to JPA persistent manager injection in JEE 5. The code looks something like this:<br /><pre><br />@MyAnnotation<br />public class WiredBean<br />{<br /> @MyInjectionAnnotation(resourceManager=AResourceType)<br /> private Resource resource;<br /><br /> public boolean isInjected()<br /> {<br /> if ( resource!=null )<br /> return true;<br /> else<br /> return false;<br /> }<br />}</pre><br />Spring allows renaming of annotations so that there is no dependency in your code on Spring classes. However to be able to inject (or autowire objects) based on your own annotation, requires some coding and essentially the following 2 things -<br /><ol><li>Create your own class that extends InstantiationAwareBeanPostProcessorAdapter ( look at PersistenceAnnotationBeanPostProcessor for an example or email me for my example)</li><li>Your Sping xml configuration needs really only 2 entries:</li><ol><li>An entry to register your own AnnotationBeanPostProcessor</li><li>An entry to scan for your own autowiring annotation that allows one to override default behavior.<br /></li></ol></ol>And you'll get code that looks like the above. Injecting your own manager objects into a JEE 5 application could be done using a Filter on the web side and Interceptors on the service/ejb side. If you are in an organization that wishes to avoid direct dependency on Spring all over the place in their JEE apps, custom annotations as I've mentioned allows for that separation.Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-22736064526934578252007-04-29T18:49:00.002-05:002008-07-18T00:09:12.235-05:00.NET ActiveXActiveX controls in the browser have been an interesting concept, especially in the Intranet environment. However their popularity has been on the decline, especially with the kind of apps that can be created with Web 2.0 technologies (mainly AJAX). However, there's still a good no of use cases where ActiveX in the browser seems a really good solution. And especially if that ActiveX component can be written as a .NET control.<br /><br />One good use of this style of architecture is when a web application needs to interact with connected devices on the client's machine such as paper/check scanners, portable devices etc. Since an ActiveX control can access local resources, interaction with such devices in a web app through the control allows you to post information back to your backend systems for processing. This makes a whole lot of sense, especially since it avoids you to write web services for communication with a backend systems written on a different platform or language (say JEE).<br /><br />A list of things that one has to remember while writing an ActiveX .NET control:<br /><ul><li>The control has to be coded as a Windows Form control with "Make Assembly COM visible"checked in the Assembly information of the Project's properties.<br /><br /></li><li>Your OBJECT tag in the HTML page points to the .NET DLL, like so -<br /><p class="MsoNormal" style="text-align: justify; line-height: 150%;"><span style="line-height: 150%;"><OBJECT id=”myControl” CLASSID=”<a href="http://server/MyApp.DLL#MyControl">http://server:port/MyApp.DLL#MyControl</a>”/></span></p></li><li>You should load the control with a javascript function for the Eolas Lawsuit workaround that prevents controls from being active on page load. In short the OBJECT tag mentioned above should be written out (using document.write) by a javascript function on a page load.<br /><br /></li><li>You need to create a security policy that needs to be pushed to the client's machine that is going to run the ActiveX component. Note here that if this is an Intranet application, rights to the control have to be defined under the LocalIntranet_Zone in the .NET Configuration management console.<br /><br /></li><li>And finally make sure your Internet Explorer policy settings allow for running "ActiveX controls and plugins".</li></ul>Looks complicated, but there are plenty of articles explaining the details as well as examples to go with it. I also was able to deploy the control to be served off a JEE application server (Weblogic) which allowed the backend to a non-microsoft solution. The tricky part here was that the dll had to be renamed so that the extension of the control was in CAPS ".DLL", and the declared mime type for a "DLL" extension was "<span style="">application/x-msdownload</span>".<br /><br />Still have questions on this - just ask here.....:). But this type of system architecture will help you leverage the best of both platforms - mainly .NET(on the frontend) and Java(on the backend).Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-81799002174508950912007-04-24T22:18:00.000-05:002008-07-05T02:40:08.726-05:00An interesting conceptOver the last couple of months, I have been contemplating on the whole blogging concept, and I finally feel ready for it. With work and research that I do day in day out, it felt hard to get one more thing in the list of things to do - and as a result, blogging just didn't make the cut . However, the way I look at this(and I am sure a lot of other people do too) is another way to document/writeup interesting findings and tidbits as I research technology, that will help me and become a reference note for me through the course of my career. And that in itself would be an invaluable asset to have. Having justified the necessity, on with the blog.......:)Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com0tag:blogger.com,1999:blog-4785913680816428471.post-35788877377244154902007-01-01T02:04:00.000-06:002009-03-14T13:35:24.546-05:00Contact AmitContact me if you are interested in securing my consulting services or have a question on something I've blogged about - <br /><form name="Contact" action="http://www.webformdesigner.net/wfd_f2.php?id=gtCGUY4an5" method="post" enctype="application/x-www-form-urlencoded"><br /><label for="Sender">Name:</label><br /><input name="formName" size="40" type="text"><br /><label for="Mail">Email:</label><br /><input name="formMail" size="40" type="text"><br /><label for="Message">Message:</label><br /><textarea name="formMsg" rows="10" cols="40"></textarea><br /><center><input value="submit" type="submit"><input name="resetBtn" value="reset" type="reset"></center><br /></form>Amithttp://www.blogger.com/profile/15889581018190525660noreply@blogger.com