12 September 2011

OpenJPA as an OSGi bundle

http://hwellmann.blogspot.com/2010/09/openjpa-and-osgi.html

06 September 2011

Create bundles for non-OSGi components

This is in German but looks helpful. http://oli.blogger.de/stories/1864695/

I'll do a write-up in English when I've tried it out.

15 June 2011

Mixing Linq-to-SQL and Linq-to-XMl

I have been trying to select a column containing XML text from a database and then selecting nodes from the XML using Linq. It didn't work. My guess is that deferred execution causes the queries to be mixed and taken as Linq-to-SQL. As a result the XML stuff causes problems.

My solution was to force an intermediate result so that there is a break between SQL and XML queries. My code for LinqPad is as follows.

var all = from bm in mytable
          select new { name=bm.SPP_USER_ID, xml=(string)bm.SPP_BOOKMARKS_XML};

var docs = from x in all
           select XDocument.Parse(x.xml);
var docs2 = docs.ToList(); // FORCE RESULT

XNamespace ns = "http://acme/bookmarks";
var href = from h in docs2.Descendants(ns + "href")
           select h.Value;  

15 April 2011

Strange and annoying problem with {NOBR}

I wrote a web app about 10 years ago which used Javascript to pop up a hidden table when an input field gets focus. Each cell in the table contains a checkbox and text which are surrounded by a NOBR to keep them together.

Recently users with IE8 complained that the first cell is not visible when the table pops up. After MUCH trial and error I narrowed it down to the NOBR tag. I replaced it with a SPAN with style set to white-space : nowrap and this seems to solve the problem :-/

05 April 2011

Using 3rd party libraries in Silverlight

I downloaded a 3rd party library for a Silverlight app I am writing. When I ran the app I got an error message telling me to add

<loadFromRemoteSources enabled="true"/>

to 'devenv.exe.config' (Usually in 'C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE').

It seems you also need to edit the 'Blocked' property of the DLL.

See How to: Use an Assembly from the Web in Visual Studio for full details.

10 March 2011

RAP + BIRT on Websphere

I used the blog from Tim Pietrusky to get started: http://blog.tim-pietrusky.de/2009/rich-ajax-platform-rap/integrating-birt-into-rap-applications/

Perhaps I did something wrong but all the image links in the resulting HTML were broken. The URL to my dynamically-generated images was invalid. Even the examples from the RAP wiki showed the same problem.

In the end I decided to store my images under /rwt-resources/birt as I noticed that all the images from RWT are loaded from this address. I also changed the URL to use a context-relative address and not a fully-defined URL with host and port. On Websphere the result was an IP address and the port of the AppServer which was not accessible directly from the client.

I set the resources extension point as follows:

<extension point="org.eclipse.equinox.http.registry.resources">
  <resource
    alias="/resources/birt"
    base-name="/rwt-resources/birt">
  </resource>
</extension>


The modified View part looks like this (sorry about the formatting):


public class ChartView extends ViewPart {
public static final String ID = "com.acme.fair.views.ChartView";

private static final String reportName = "simplechart.rptdesign";
private static final String reportDirLocal = "/resources/birt/";
private static final String reportDirServer = "/rwt-resources/birt/";

private Browser browser;
private String reportDesign; // Full path to the local BIRT report file
private String URL;

private IReportEngine engine = null;
private EngineConfig config = null;
private IReportRunnable design = null;
private IRunAndRenderTask task;

@SuppressWarnings("restriction")
public void createPartControl(Composite parent) {
this.setPartName("BIRT in RAP");
browser = new Browser(parent, SWT.NONE);
configureURL();

try {
config = new EngineConfig();
IReportEngineFactory factory = (IReportEngineFactory) Platform
.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
engine = factory.createReportEngine(config);

InputStream fs = null;
try {
URL url = Activator.getDefault().getBundle().getResource("/resources/birt/simplechart.rptdesign");
fs = url.openStream();
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}

design = engine.openReportDesign(fs);

// Create task to run and render the report
task = engine.createRunAndRenderTask(design);

// Set the dataset for the chart as report parameter
task.setParameterValue("CHART_DATASET", MesseSql.getFairsPerYear());

// Render the report to HTML
HTMLRenderOption renderOptions = new HTMLRenderOption();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
renderOptions.setOutputFormat(HTMLRenderOption.HTML);
renderOptions.setOutputStream(outputStream);

// Get the path to the local context directory to save the rendered
// chart image
String webAppBase = (ContextProvider.getWebAppBase()).replaceAll("\\\\", "/");
String path = webAppBase + reportDirServer + RWT.getSessionStore().getId();

// Handle the image path
renderOptions.setImageHandler(new HTMLServerImageHandler());
renderOptions.setImageDirectory(path);
renderOptions.setBaseImageURL(RWT.getRequest().getContextPath() + reportDirServer + RWT.getSessionStore().getId());

task.setRenderOption(renderOptions);
task.run();
task.close();

// Set the HTML output to the Browser widget
browser.setText(outputStream.toString());

engine.destroy();

} catch (Exception ex) {
ex.printStackTrace();
}
}

// Set the URL for the BIRT report for different environments.
private void configureURL() {

// Protocol, ip & port
ServletContext sc = RWT.getRequest().getSession().getServletContext();
String realPath = sc.getRealPath("/");
HttpServletRequest request = RWT.getRequest();
String protocol = "http://";
String ip = request.getLocalAddr();
int port = request.getLocalPort();
URL = protocol + ip + ":" + port;
String webAppName = "";

if (realPath == null) { // Start application locally within Eclipse
// (Windows)
reportDesign = URL + reportDirLocal + reportName;
} else { // Start application on a server (Apache Tomcat or so)
webAppName = sc.getContextPath();
reportDesign = URL + webAppName + reportDirLocal + reportName;
URL = URL + webAppName;
}
}

public void setFocus() {
}

/**
* Execute the given script, for example to print the

* content of the Browser
*
* @param script
* String to be executed
*/
public void executeScript(String script) {
browser.execute(script);
}
}

11 February 2011

RAP: Useful snippets

Just want to record some handy code snippets...

Save/Restore workbench state

In the Application WorkbenchAdvisor


/**
* set auto restore of workbench state
*/

public void initialize( IWorkbenchConfigurer configurer ) {
    getWorkbenchConfigurer().setSaveAndRestore( true );
    super.initialize( configurer );
}

10 February 2011

RAP: App suddenly stopped working

I edited the Preference feature in my app and could not start the app. I was getting the following error:

java.lang.IllegalArgumentException: no layout registered with default id (LayoutRegistry.DEFAULT_LAYOUT_ID) or no layout activated over branding extension.
at org.eclipse.rap.ui.interactiondesign.layout.ElementBuilder.<init>(ElementBuilder.java:96)
at org.eclipse.rap.internal.design.example.builder.DummyBuilder.<init>(DummyBuilder.java:23)
at org.eclipse.rap.internal.design.example.managers.CoolBarManager.<init>(CoolBarManager.java:140)
Turns out that the cookies have got themselves in a muddle and need to be deleted. I don't like to delete all my cookies so I (in IE8) opened Tools -> Internet options -> Browsing history -> Settings -> View files. This shows all the temp files. I sorted by last changed date and deleted the files which looked like 'Cookie@127.0.0.1'

Then it all worked again.

09 February 2011

RAP: First deploy to WebSphere

It didn't work first time but it didn't take too long to get the first results. This is what I did.

  • Ensure RAP WAR Products feature installed -- http://wiki.eclipse.org/RAP/Equinox_WAR_products
  • Create a new WAR Product Configuration in the plugin project. New -> Other... -> Plugin Development
  • Select parent folder, name the product and choose the lauch configuration
  • Open the WAR product file and enter an ID and Name
  • On the configuration page add the JARs used by the project
  • Return to the Overview page and select Validate
  • If necessary, add the missing plugins or JARs
  • Start the export wizard and enter the name of the output file. Press Finish.
  • The WAR file has now been exported
  • Open the Websphere Integrated Solutions Console
  • Create new Application Server. I called it RAP_TEST.
  • I had to modify a few ports because the defaults clashed with other App Servers
  • Install new Enterprise Application and enter the name of the WAR file
  • Accept all defaults and enter a context root such as /apps/rap
  • Finish
  • Might need to sync nodes etc but should now work
  • <servername>/apps/rap/fair?startup=fair (in my case)
So, my app kind of works. Unfortunately, the whole branding is missing so there are no images, styles etc. When I find the cause, I'll post more here.

Missing images problem

I set up a simple Tomcat server to check that it wasn't a WAS problem. I then noticed that there was an exception in the logs. Something to do with Jetty and an 'Address already in use' bind error. I was surprised that Jetty would be active on the Tomcat server so I checked my plugin dependencies. In the end I removed all the dependencies and added the 'Required plugins'. That seemed to cure the problem. After redeploying, there were no Jetty exceptions and I get the images which were missing.

08 February 2011

Strangeness(?) with RAP i18n

Just made my first attempt to add multi-language support to my RAP app. I created a default bundle for English and then one for German.

messages.properties
messages_de.properties

My browser was setup to accept German and English in that order so I got the German texts. I then swapped the language prefs in the browser to put English first but I still got German. I tried closing the browser, restarting the app etc. but I still got German. Finally, I added a new bundle, messages_en.properties and now I get English.

Is this the correct behaviour? It is not what I expected but I guess nothing is known about the default bundle and the browser is saying that German is acceptable (if not preffered), Hmmm...


UPDATE
the explanation is as follows:

your VM is set to German, right? What happens is that the
Browser asks for English, but RWT does not find a messages_en.properties
file. So it tries the default locale, in your case German and Bingo!
there is a messages_de.properties file. So you get German. If you want to
have English as your fallback, set your VM to English. Does this explain
the behavior?

Regards, Ralf

--
Ralf Sternberg

I18n in RAP. What a chore!

I18n is bad enough, but in RAP there is even more typing to do :-(

You need to create a Messages class and add a public field for every string you need to translate. You then have to create a properties file for each language and add the texts. The convention for key names is Classname_fieldname.

For example:

Messages.java
...
public String MyView_controltext;
...

Messages.properties
...
MyView_controltext = Hello World
...

MyView.java
...
control.setText(Messages.get().MyView_controltext);
...

I made life a liitle easier by adding a template. Window -> Preferences -> Java -> Editor -> Templates -> New...
Name = msg (or whatever you like)
Pattern = Messages.get().${enclosing_type}_${cursor}

Now I can just type 'msg' <Ctrl>+Space and I get most of what I need.

I can also recommend the Eclipse ResourceBundle Editor at http://sourceforge.net/projects/eclipse-rbe/.

25 January 2011

Proxy frustrations

Wasting heaps of time trying to access the eclipse & RAP CVS repositories from behind the company firewall & proxy. Been through all the help pages I can find but no success. The admins here say that SOCKS is not allowed but it ought to be possible to get at proxy.eclipse.org using port 80. Why is it not working?!

Grrrrr :-(

21 January 2011

Using the JFace forms package from the RAP incubator

I wanted to use the collapsible Section control so I downloaded the JFace Forms package from the RAP source repository :pserver:dev.eclipse.org:/cvsroot/rt .

Just import org.eclipse.rap.ui.forms and add to the main plugin Dependencies and it's done. As I understand it, the forms package is not yet official so I guess there might be some bugs. In fact, the section twistie doesn't react to the mouse click but the title section does so it's not a major problem.

19 January 2011

Coding vs Configuration

After a very frustrating afternoon trying to understand the configuration of ActionSets, Activities, Services etc - without success - I am wondering just how necessary it all is when writing a one-off RAP application. There is just the one plug-in and it will never be added to another plug-in set and will never have to co-operate or negotiate with other plug-ins.

So is it really necessary to do all this configuration? Can I do away with x layers of abstraction and just code the stuff I need directly? That would seem to be the pragmatic approach but I wonder what the consequences are are the project gets bigger.

18 January 2011

Role-based security in RAP

Been struggling this afternoon with role-dependent actions. I want to disable some actions unless the current user has the 'admin' role.

Found this document http://ftp.bredex.de/rcp-auth/RCP_Authorization.pdf which looks interesting. There is also a FAQ on the RAP site which covers this topic but I couldn't get it to work as I expected. The downloadable demo didn't function either :-(

More info found here https://bugs.eclipse.org/bugs/show_bug.cgi?id=71857
You could try using the activities mechanism for this.
See 
http://help.eclipse.org/help30/topic/org.eclipse.platform.doc.isv/guide/workbench_advext_activities.htm

You would:
- define separate activities corresponding to the different access levels
- define your actions in regular action sets, grouped according to access level
- associate each activity with the appropriate action sets via
activityPatternBinding elements
- set the enabled activity ids after authentication, early in the workbench
lifecycle, e.g. from your WorkbenchAdvisor's preStartup() method.

You may want to define dependencies between access levels (e.g. level A includes
level B) using the activityRequirementBinding element.

Note that this mechanism also supports dynamic changes to the set of enabled
activities.

An article from IBM http://www.ibm.com/developerworks/opensource/library/os-ecl-rcpsec/index.html

RAP Wiki http://wiki.eclipse.org/RAP/Equinox_Security_Integration

RAP forums & resources

FORUMS
Eclipse.org http://www.eclipse.org/forums/index.php?t=thread&frm_id=34&S=424f561068bca8cd9e7e5945e52bafdf

RAP Forum: http://www.eclipse.org/forums/index.php?t=thread&frm_id=34

CASE STUDIES
CAS http://www.infoq.com/articles/eclipse-rap-casestudy

First simple app in RAP

Got my first simple RAP application running. I used the RAP Mail template to get started and have 2 views: one for navigation and the other to show details of the selection. The application I'm working on is for trade fair management.

There is still a lot of 'mail' stuff visible which I haven't been able to get rid of yet but here are a few things I did to customize the example.

  • Refactor packages and classes to better reflect the application e.g. all 'mail' changed to 'fair'
  • plugin.xml -> Extensions -> ...ui.branding. Changed 'servletName' from 'mail' to 'fair'
  • plugin.xml -> Extensions -> ...ui.entrypoint. Changed 'parameter' from 'mail' to 'fair'
The default branding is not to my taste at all. This will be something to look at soon but seems to be quite extensive.
The packaged examples are worth looking at. Locate 'org.eclipse.rap.design.example' and 'org.eclipse.rap.demo' in the Plug-ins view and then Import As -> Source project.

I find these a very useful reference and used a number of items from org.eclipse.rap.demo.controls.TableViewerTab for my navigation view.


As I don't like the branding I edited the plug-in to remove the template's branding and replaced it with a default.


And the application now looks quite different.



17 January 2011

Class path problems in eclipse plug-ins

As I mentioned in a previous post, out of desperation I added the DB2 jar to an eclipse plug-in. I then innocently tried to load it using:

try {
    Class.forName("com.ibm.db2.jcc.DB2Driver");
} catch (ClassNotFoundException e) {
    Activator.logError("getConnection", e);
    throw e;
}
return DriverManager.getConnection("jdbc:db2://servername", "user", "pwd");

This did not work. Eclipse plug-ins have their own class loader and the DB2 jar must be added to the plug-in classpath.

Open the plugin.xml and select the 'Runtime' tab. In the 'Classpath' section select 'Add...' and choose the DB2.jar (and any other JARs which are needed).

Best practice (I would guess) would be to have separate plug-ins for each external library (log4j, db2 etc).

RAP: First difficulties - how to define a database connection

I have been working on J2EE projects for many years and am used to defining resouces such as DB connections in the EAR project. The connection is picked up at runtime using a JNDI lookup. Scripts are used to modify the actual connection details depending on the target environment: test, stage, production etc.

So how should this be done in RAP? At the end of the day it will also be a J2EE application and we will want to deploy to one of a number of target systems. How well will it integrate in our existing deployment system?

After a lot of head scratching I decided to adopt the pragmatic (impatient) approach and bunged the DB2 jar into the project just so that I could get on with the interesting stuff.

As soon as I find a better approach (there had better be one!) I will post again here.

UPDATES:

Howto access backend services from RAP application?

Installing RAP

This is my first post on the subject of RAP (Rich Ajax Platform for eclipse). I want to document my progress as I delve into RAP and attempt to produce a full-size, real-world application.

Here are the steps I took to install RAP and get the first simple app running:
  • Download the RAP package from http://www.eclipse.org/downloads/ (select Eclipse for RCP and RAP Developers)
  • Extract the zip file to a location of your choice
  • Start eclipse.exe
  • When prompted for a workspace path enter, for example, D:\Workspaces\RAP
  • When eclipse has started, the welcome page is displayed. Click on the 'Overview' icon and then on the 'Rich Ajax Platform (RAP)' link. 
  • Select the 'Install Target Platform' link and follow the instructions. At the time of writing, this step has to be performed. If you do not perform this action the projects will contain 100s of errors such as 'import org.eclipse.* not found'. If you forget this step you can get back to the Welcome page using Help -> Welcome.
  • You should now have a new target platform. To double-check, view the preferences: Window -> Preferences -> Plug-in Development -> Target Platform. There should be a Rich Ajax Platform (active) target
  • Create a new plugin project. File -> New -> Project... -> Plug-in Development -> Plug-in Project
  • Enter the name of the project and select 'Next'.
  • There is no need to change anything on the 'Content' dialog. Select 'Next'.
  • Choose a RAP template e.g. RAP Mail Template and select 'Finish'.
  • The project has been created and there should also be a new Run/Debug configuration. See Run -> Run Configurations... There should be a new configuration in the 'RAP Application' section. Select it and click on 'Run'.
  • The browser tab should now open and adter a few seconds the application will be visible.
This completes the first post. I hope there will be more to follow.