Deals with Petals ESB, Petals Suite, SOA, PetalsLink…
The videos of all the OW2Con2011 have been published to the OW2 Youtube channel. My talk about Petals BPM and The Cloud is also available.
You are right, I need to smile more, be less tired and have a demo of the BPM editor working on low resolution displays… BTW, the demo of the DSB Monitoring & Management console used to deploy and monitor BPEL process works.
In: Vincent Zurczak
6 Jan 2012Salut.
Voilà un rapide tutoriel pour vous apprendre à créer un dégradé (circulaire) autour d’une image. Le but est de mettre en valeur le centre ou une partie de l’image et d’atténuer les bords. Et j’en fais un article parce que j’ai passé une grosse demi-heure à chercher comment faire, que ce soit sur le net et en bidouillant dans The Gimp.
Voilà ce à quoi on veut arriver :
On commence par ouvrir notre image de départ avec The Gimp.
Afin de ne pas pourrir l’originale, on duplique l’image (menu Image > Dupliquer).
Rajoutez un calque et le remplir de la couleur ou du motif à utiliser. Dans cet exemple, je vais utiliser un fond noir. Laissez ce deuxième calque au-dessus de l’autre.
Assurez-vous que le 2ème calque est bien sélectionné (c’est important), puis ajoutez-lui un masque de calque (menu Calque > Masque > Ajouter un masque de calque…). Une boite de dialogue apparaît : choisissez Noir (transparence totale).

Dans la fenêtre des calques, vous devriez donc voir…
Sélectionnez maintenant l’outil Dégradé, PP vers AP (RGB) et une forme radiale.

Dans la fenêtre des calques, assurez-vous que le 2ème calque (noir ici) est bien sélectionné, et que le focus est sur le masque de calque (en gros, vous cliquez sur le carré à droite dans le calque). Allez maintenant sur votre image et dessinez un cercle qui donnera le focus à la partie de l’image que vous voulez valoriser. Pour rappel, l’outil dégradé en mode radial prend 2 points : le premier clic détermine le centre du cercle, et le deuxème permet de définir un rayon.
Miracle, ça marche… Même s’il vous faudra peut-être plusieurs essais pour arriver au bon réglage.
Dans les calques, le dégradé apparaît sur le masque de calque (que vous aviez sélectionné avant).
Après, il vous suffit de redécouper l’image pour dégager les bords superflus.
Notez que ça marche bien pour les sélections circulaires. Pour d’autres formes, on peut jouer avec d’autres dégradés, ou bien travailler / déformer le calque avec le dégradé (par exemple pour arriver à une ellipse au lieu d’un cercle). Et j’ai bien dit travailler le calque, pas l’image.
In: Vincent Zurczak
6 Jan 2012Salut.
Voilà un rapide tutoriel pour vous apprendre à créer un dégradé (circulaire) autour d’une image. Le but est de mettre en valeur le centre ou une partie de l’image et d’atténuer les bords. Et j’en fais un article parce que j’ai passé une grosse demi-heure à chercher comment faire, que ce soit sur le net et en bidouillant dans The Gimp.
Voilà ce à quoi on veut arriver :
On commence par ouvrir notre image de départ avec The Gimp.
Afin de ne pas pourrir l’originale, on duplique l’image (menu Image > Dupliquer).
Rajoutez un calque et le remplir de la couleur ou du motif à utiliser. Dans cet exemple, je vais utiliser un fond noir. Laissez ce deuxième calque au-dessus de l’autre.
Assurez-vous que le 2ème calque est bien sélectionné (c’est important), puis ajoutez-lui un masque de calque (menu Calque > Masque > Ajouter un masque de calque…). Une boite de dialogue apparaît : choisissez Noir (transparence totale).

Dans la fenêtre des calques, vous devriez donc voir…
Sélectionnez maintenant l’outil Dégradé, PP vers AP (RGB) et une forme radiale.

Dans la fenêtre des calques, assurez-vous que le 2ème calque (noir ici) est bien sélectionné, et que le focus est sur le masque de calque (en gros, vous cliquez sur le carré à droite dans le calque). Allez maintenant sur votre image et dessinez un cercle qui donnera le focus à la partie de l’image que vous voulez valoriser. Pour rappel, l’outil dégradé en mode radial prend 2 points : le premier clic détermine le centre du cercle, et le deuxème permet de définir un rayon.
Miracle, ça marche… Même s’il vous faudra peut-être plusieurs essais pour arriver au bon réglage.
Dans les calques, le dégradé apparaît sur le masque de calque (que vous aviez sélectionné avant).
Après, il vous suffit de redécouper l’image pour dégager les bords superflus.
Notez que ça marche bien pour les sélections circulaires. Pour d’autres formes, on peut jouer avec d’autres dégradés, ou bien travailler / déformer le calque avec le dégradé (par exemple pour arriver à une ellipse au lieu d’un cercle). Et j’ai bien dit travailler le calque, pas l’image.
In: Eclipse
5 Jan 2012I have recently committed in the Eclipse BPEL Designer some patches that were contributed in our Bugzilla. This fact itself is not important. However, I used the Git command apply and kept the author name in the commit. I had never used this feature before, but it is extremely powerful. And very convenient to track activities and propose new committers on a project.
I let some traces in this article (as an example and for me, for later).
Notice that the apply command did not work with EGit, I had to use the command line. I guess it will be fixed in a future version.
git apply --stat myPatchFile
git apply --check myPatchFile
git apply myPatchFile
Then, you can check that the patch works and then commit it, before pushing the modification.
One important thing is to keep the author’s name in the commit. The author and the committer are different. And both can be kept in the commit and in the history. Here is an example in the command line:
git commit -a --author="authorUsername <author.mail.address@sth.com>"
After the push, both the author and commiter names will appear in the repository.
I don’t know if everyone in Eclipse projects uses this feature, but from the community perspective, this is very interesting (IMO).
In: Eclipse
4 Jan 2012With SWT, tab folders are a way to integrate in a same container several widgets. However, it appears to be quite limited in terms of design and creativity. I here propose some alternatives for sexier user interfaces.
This is our witness section.
Here is a snippet (the full code is avilable at the end of the article)…
public void createTabs( Composite parent ) {
final TabFolder tabFolder = new TabFolder( parent, SWT.NONE );
tabFolder.setLayoutData( new GridData( GridData.FILL_BOTH ));
for( int i=0; i<=4; i++) {
TabItem tabItem = new TabItem( tabFolder, SWT.NONE );
tabItem.setText( "Item " + i );
tabItem.setControl( createTabContent( tabFolder ));
}
}
private Composite createTabContent( Composite parent ) {
Composite c = new Composite( parent, SWT.NONE );
c.setLayout( new GridLayout( 2, false ));
String[] properties = { "First Name:", "Last Name:", "Nick Name:" };
for( String property : properties ) {
new Label( c, SWT.NONE ).setText( property );
new Text( c, SWT.SINGLE | SWT.BORDER ).setLayoutData( new GridData( GridData.FILL_HORIZONTAL ));
}
return c;
}
And here is a screenshot.
As you can see, everything is centered, except the tabs.
And that’s not cool at all.
The CTabFolder class is a little more powerful, but similar limitations appear quickly. It is not possible to center the tabs. And they are either above or below the content, never on side.
public void createTabs( Composite parent ) {
final CTabFolder tabFolder = new CTabFolder( parent, SWT.BORDER );
tabFolder.setLayoutData( new GridData( GridData.FILL_BOTH ));
tabFolder.setSimple( false );
for( int i=0; i<=4; i++ ) {
CTabItem tabItem = new CTabItem( tabFolder, SWT.NONE );
tabItem.setText( " Item " + i + " " );
tabItem.setControl( createTabContent( tabFolder ));
}
}
Note that you can add images on the tab.
An alternative to these classes is ScrolledPageBook.
It can be used in Eclipse plugins, but also in standalone applications. In addition to SWT bundles, you only have to add org.eclipse.ui.forms to your classpath. No need to be in a form to use it.
Let’s see a first illustration, with navigation labels and not (yet) tabs.
The principle is simple: you have a set of labels and a scrolled page book. When the user clicks on a label, we change the displayed page in the book.
public void createTabs( Composite parent ) {
// Add the container for navigation labels
final int tabCpt = 5;
Composite container = new Composite( parent, SWT.NONE );
container.setLayout( new GridLayout( tabCpt, true ));
container.setLayoutData( new GridData( SWT.CENTER, SWT.DEFAULT, true, false ));
// Add the page book
final ScrolledPageBook pageBook = new ScrolledPageBook( parent );
pageBook.setLayoutData( new GridData( GridData.FILL_BOTH ));
// The listener when the user clicks on a "tab"
Listener listener = new Listener() {
@Override
public void handleEvent( Event event ) {
pageBook.showPage( event.widget.getData());
}
};
// Register the pages and bind it all
for( int i=0; i<=4; i++ ) {
Label l = new Label( container, SWT.BORDER );
l.setText( "Item " + i );
l.setData( i );
pageBook.registerPage( i, createTabContent( pageBook.getContainer(), i ));
l.addListener( SWT.MouseDown, listener );
}
// Force to display the first tab
pageBook.showPage( 0 );
}
And here is a preview.
Ugly, isn’t it?
But we can fix it.
To have a real tab’s look & feel, we have to reduce the margin between the content and the labels. We also need make our labels look better. Partial borders will be added around the labels thanks to a paint listener.
Here is the code (it’s a little bit longer than before).
/**
* Remember the selected index.
*/
private Integer selectedIndex = 0;
/**
* Creates the tabs.
* @param parent the parent
*/
public void createTabs( Composite parent ) {
// Add the container for navigation labels
final int tabCpt = 5;
Composite container = new Composite( parent, SWT.NONE );
GridLayout layout = new GridLayout( tabCpt, true );
layout.marginHeight = 0;
container.setLayout( layout );
container.setLayoutData( new GridData( SWT.CENTER, SWT.DEFAULT, true, false ));
// Add the page book
final ScrolledPageBook pageBook = new ScrolledPageBook( parent );
pageBook.setLayoutData( new GridData( GridData.FILL_BOTH ));
// The listener when the user clicks on a "tab"
final List<Label> navigationLabels = new ArrayList<Label> ();
Listener listener = new Listener() {
@Override
public void handleEvent( Event event ) {
pageBook.showPage( event.widget.getData());
// Remember the last selected index
TabsWithScrolledPageBookSnippet.this.selectedIndex = (Integer) event.widget.getData();
// Highlight the selected tab
for( Label l : navigationLabels ) {
Color color;
if( l != event.widget && l.getParent() != event.widget )
color = Display.getDefault().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND );
else
color = Display.getDefault().getSystemColor( SWT.COLOR_WHITE );
l.setBackground( color );
l.getParent().setBackground( color );
}
}
};
// The paint listener, to paint partial borders
PaintListener paintListener = new PaintListener() {
@Override
public void paintControl( PaintEvent event ) {
Color color;
if( TabsWithScrolledPageBookSnippet.this.selectedIndex.equals( event.widget.getData()))
color = Display.getDefault().getSystemColor( SWT.COLOR_GRAY );
else
color = Display.getDefault().getSystemColor( SWT.COLOR_WIDGET_DARK_SHADOW );
Rectangle rect = ((Composite) event.widget).getBounds();
event.gc.setForeground( color );
event.gc.setAntialias( SWT.ON );
event.gc.drawLine( 0, 0, rect.width - 1, 0 );
event.gc.drawLine( 0, 0, 0, rect.height - 1 );
event.gc.drawLine( rect.width - 1, 0, rect.width - 1, rect.height - 1 );
}
};
// Register the pages and bind it all
for( int i=0; i<tabCpt; i++ ) {
Label l = createTabLabel( i, container, paintListener, listener );
navigationLabels.add( l );
pageBook.registerPage( i, createTabContent( pageBook.getContainer(), i ));
}
// Force to display the first tab (and force it to be highlighted)
navigationLabels.get( 0 ).notifyListeners( SWT.MouseDown, new Event());
}
/**
* Creates a label for the tab (wrapped in a composite for better display).
* @param index the tab index
* @param parent the container for the label
* @param paintListener the paint listener for the label's container (to paint partial borders)
* @param mouseDownListener the listener for when a tab is selected
* @return the created label
*/
private Label createTabLabel( int index, Composite parent, PaintListener paintListener, Listener mouseDownListener ) {
// Wrap the labels in a composite
Composite c = new Composite( parent, SWT.NONE );
c.setLayout( new GridLayout());
c.setLayoutData( new GridData( 80, 25 ));
c.setData( index );
// To paint partial borders
c.addPaintListener( paintListener );
// Deal with the content
Label l = new Label( c, SWT.NONE );
l.setLayoutData( new GridData( SWT.CENTER, SWT.CENTER, true, true ));
l.setText( "Item " + index );
l.setData( index );
// The click listener
l.addListener( SWT.MouseDown, mouseDownListener );
c.addListener( SWT.MouseDown, mouseDownListener );
return l;
}
By playing with the previous example, we can also obtain a result similar to the Eclipse tabbed properties. In the following example, the navigation labels are placed on the left of the content. I hardly changed the code (about 10 lines, it is just about the layout).
The code is available in the archive below.
I hope these snippets (and screenshots) will help some of you.
They also illustrate the use of the Scrolled Page Book class. Obviously, this could be used to create a custom and reusable widget (as an example shared in the Nebula project). No need to say that it would be more simple with a HTML and CSS approach. E4 may help in such an approach.
The complete source code for the snippets is available in this archive.
In: java
20 Dec 2011I have 2 applications that should work together.
These applications are end-user applications. The link between them is in fact the system’s clipboard (this is a Windows 7′s use case, but it might be encountered on other platforms). Basically, the idea is that the user selects an image in the first application and copies it in the clipboard. The second application should detect this new image and process it.
By browsing the web, I found out that there is no perfect solution. Sun did not provide a complete solution for this in Java because there were portability issues. One alternative was to use the ava.awt.datatransfer.ClipboardOwner class. A subclass instance acquires the ownership of the clipboard by putting something into it. When another application copies something into the clipboard, the previous owner is notified that it has lost the ownership. The implementation would be something like:
public class ClipboardWatcher implements ClipboardOwner {
/**
* @see java.awt.datatransfer.ClipboardOwner
* #lostOwnership(java.awt.datatransfer.Clipboard, java.awt.datatransfer.Transferable)
*/
@Override
public void lostOwnership( Clipboard clipboard, Transferable contents ) {
// Get the clipboard's content and process it if required
// ...
// Acquire the ownership again by putting the same content
// (Same content because otherwise, copy/paste does not work anymore for other applications)
// ...
}
}
This is not very convenient.
I also discovered it was not working very well when there are several running applications.
So, I implemented a solution with a thread which polls the clipboard regularly. I put here a complete sample with an example of image processing.
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.imageio.ImageIO;
/**
* @author Vincent Zurczak
*/
public class ClipboardWatcher implements ClipboardOwner {
static final File PREVIEW_DIRECTORY = new File( System.getProperty( "java.io.tmpdir" ), "Image-Store" );
private final List<PreviewFileListener> listeners;
private final SimpleDateFormat sdf;
private final AtomicBoolean run;
/**
* Constructor.
*/
public ClipboardWatcher() {
this.listeners = new ArrayList<PreviewFileListener> ();
this.sdf = new SimpleDateFormat( "yy-MM-dd---HH-mm-ss" );
this.run = new AtomicBoolean( true );
if( ! PREVIEW_DIRECTORY.exists()
&& ! PREVIEW_DIRECTORY.mkdir()) {
// TODO: process this case in a better way
System.out.println( "The preview directory could not be created." );
}
}
/**
* @param e
* @return
* @see java.util.List#add(java.lang.Object)
*/
public boolean addPreviewFileListener( PreviewFileListener e ) {
synchronized( this.listeners ) {
return this.listeners.add( e );
}
}
/**
* @param o
* @return
* @see java.util.List#remove(java.lang.Object)
*/
public boolean removePreviewFileListener( PreviewFileListener o ) {
synchronized( this.listeners ) {
return this.listeners.remove( o );
}
}
/**
* @see java.awt.datatransfer.ClipboardOwner
* #lostOwnership(java.awt.datatransfer.Clipboard, java.awt.datatransfer.Transferable)
*/
@Override
public void lostOwnership( Clipboard clipboard, Transferable contents ) {
// Acquire the ownership again is not working very well for a periodic check
}
/**
* Starts polling the clipboard.
*/
public void start() {
// Define the polling delay
final int pollDelay = 5000;
// Create the runnable
Runnable runnable = new Runnable() {
@Override
public void run() {
Transferable contents = null;
while( ClipboardWatcher.this.run.get()) {
// Get the clipboard's content
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
try {
contents = clipboard.getContents( null );
if ( contents == null
|| ! contents.isDataFlavorSupported( DataFlavor.imageFlavor ))
continue;
Image img = (Image) clipboard.getData( DataFlavor.imageFlavor );
saveClipboardImage( img );
clipboard.setContents( new StringSelection( "The clipboard watcher was here!" ), ClipboardWatcher.this );
} catch( UnsupportedFlavorException ex ) {
ex.printStackTrace();
} catch( IOException ex ) {
ex.printStackTrace();
} catch( Exception e1 ) {
// We get here if we could not get the clipboard's content
continue;
} finally {
try {
Thread.sleep( pollDelay );
} catch( InterruptedException e ) {
e.printStackTrace();
}
}
}
}
};
// Run it in a thread
Thread thread = new Thread( runnable );
thread.start();
}
/**
* Stops listening.
*/
public void stop() {
this.run.set( false );
}
/**
* Saves the image residing on the clip board.
*/
public void saveClipboardImage( Image img ) {
if( img != null ) {
if( img instanceof BufferedImage ) {
try {
File file = new File( PREVIEW_DIRECTORY, this.sdf.format( new Date()) + ".jpg" );
ImageIO.write((BufferedImage) img, "jpg", file );
for( PreviewFileListener listener : this.listeners )
listener.newCreatedFile( file );
} catch ( IOException e ) {
e.printStackTrace();
}
} else {
System.out.println( "Unsupported image: " + img.getClass());
}
}
}
/**
* A interface to listen to image detection.
*/
public interface PreviewFileListener {
/**
* Notifies this instance that an image file was created from the clip board.
* @param imageFile the image file that was saved on the disk
*/
void newCreatedFile( File imageFile );
}
}
There is another alternative for Windows platforms.
However, it was only implemented for an OSGi context. Notice that it should not be too difficult to adapt it for standalone Java applications. I read and understood most of the code, but I was a little bit lazy on this one. Check this blog entry for more details. The code is hosted on GitHub.
In: Vincent Zurczak
20 Dec 2011Pour poster sur WordPress, tout le monde sait que l’on peut le faire en passant par le panneau d’administration de son blog. Vous connaissez peut-être aussi des programmes qui vous permettent de poster directement sur votre blog, sans avoir à lancer votre navigateur web. Une liste de tels programmes est disponbile sur le site de WordPress.
En fait, ces applications peuvent publier des billets et interagir avec votre blog grâce à un script particulier, intégré aux blogs WordPress. Ce script PHP s’appelle xmlrpc.php et permet de communiquer via HTTP en échangeant des structures JSON. Autrement dit, pour qu’une de vos applications puisse interagir avec votre blog, il suffit qu’elle communique avec ce fameux script.
Dans le cas d’une application Java, plusieurs options sont possibles.
Personnellement, je n’avais pas envie de me prendre la tête pour décortiquer toutes les structures de données de l’API WordPress. Je me suis donc tourné vers une librairie Java qui fournit une API propre (et à peu près claire). Cette librairie, c’est WordPress-Java.
Il y a quelques exemples disponibles sur le site.
Je me permets ici d’en rajouter un de ma composition.
import java.net.MalformedURLException;
import net.bican.wordpress.Page;
import net.bican.wordpress.Wordpress;
import redstone.xmlrpc.XmlRpcArray;
import redstone.xmlrpc.XmlRpcFault;
/**
* @author Vincent Zurczak
*/
public class WordpressDemo {
/**
* Publishes the given posts on the blog.
*/
public static void publishOnBlog() {
String username = "mon-nom-d'utilisateur";
String pwd = "mon-mot-de-passe";
String xmlRpcUrl = "http://mon-adresse-de-blog/xmlrpc.php";
try {
Page newPost = new Page();
newPost.setTitle( "Le titre de mon post" );
newPost.setExcerpt( "Un résumé de mon billet" );
newPost.setMt_keywords( "mot clé 1, mot clé 2" ); // Tags
newPost.setMt_allow_comments( 1 ); // Allow comments
newPost.setMt_allow_pings( 0 ); // No ping
newPost.setDescription( "Le contenu de mon post, avec des liens, etc." );
XmlRpcArray cats = new XmlRpcArray();
cats.add( "Technique" );
newPost.setCategories( cats ); // Post categories
Wordpress wp = new Wordpress( username, pwd, xmlRpcUrl );
wp.newPost( newPost, true );
} catch( MalformedURLException e ) {
e.printStackTrace();
} catch( XmlRpcFault e ) {
e.printStackTrace();
}
}
}
Après, vous pouvez faire des trucs plus avancés.
Mais les tags, les catégories et les éléments utilisés ici sont les plus courants.
One more time, one more tiny (and maybe useful in some cases…) application with Play!.
WTF, my server is dead again!?
This app is a simple heartbeat manager looking at remote HTTP services and notifying you by email when something becomes unreachable. It uses the background Job feature of the Play framework and just does HTTP GETs on the specified list. That’s all, that’s simple, but that’s can be useful sometimes…

The code is located at https://github.com/chamerling/heartbeat-manager
I started to develop QuickHub some weeks ago by focusing on features and without taking into account security issues such as this critical information which are login and password credentials… As mentioned in the GitHub developer pages, I started to use Basic Auth for all the requests QuickHub does to get retrieve data from GitHub. I started to think about moving to OAuth when a user said me that he bought QuickHub but that he did not use it because of Basic Auth. He was afraid that I can rob its credentials and so have a look to its repositories and more. I totally understand this argument and so I started to think that it limits QuickHub adoption by developers and that I should do something.
So, I discussed with GitHub guys through their support channel (Here I want to say that I am really impressed on how fast and professional is the GitHub support team!). Of course, they also told me that they will never use QuickHub if OAuth is not provided. After discussions with the guys, I started to implement a workaround to provide OAuth support in QuickHub by using the OAuth Web flow and adding some stuff to QuickHub.
Let’s see how we can do that in a generic way so that you can use it in your app if needed since every serious Internet service also provide OAuth support… Note that I will not give many details about OAuth itself but I will use some terms, so have a look to OAuth documentation for more details.
The first step is to register your application to the developer portal. Here you need to provide some information such as the app name and its callback URL. Even if we are developing a desktop app and not a Web one, we need to be able to provide this HTTP based callback URL. We will see in the next section what is inside this application. By registering our application, the service will generate and give us some keys to be used in the next steps, mostly to recognize us when calling the service.
We need a Web application to handle callback calls from the service we want to use OAuth. This application will only be used at authorization time and just have to be able to receive the service call, get the code sent by the service, then call the service again with the code and our application keys (there is a secret one to be used here). As a result, the service will send you back your OAuth token to be used in all the future service calls. This token is used to authenticate your service calls, no more password stuff inside! Here is a quick sequence diagram showing all the exchanges between actors…

On the QuickHub side, I chose to create this Web application by using the Play Framework I already mentioned several times in this blog. I used the Heroku paas to provide the Web application publicly.
As showed in this Gist (https://gist.github.com/1466592), the callback method is really simple (as usual with Play!): just get the code and call GitHub with it and your application keys. When all lis done, just display a result page with a specific URL. Here it starts with ‘quickhubapp://oauth?’. Let’s see what it means in the next section…
Once the desktop application is authorized, our Web application redirects the user to a Web page which embeds a button targeting an URL starting by ‘quickhubapp://oauth?’. Here you already understand that by clicking on such a link must drive you to something special. The cocoa framework allows developers to register specific URL handlers for their applications. So we need to register QuickHub handlers so that OS X knows that every link with the quickhubapp scheme must me routed to QuickHub. This is as easy as showed in this Gist https://gist.github.com/1466628.
This code snippet just tells QuickHub to invoke the getUrl method when it receives a quickhubapp event. Up to the getUrl method to handle things. In QuickHub, I just extract the OAuth token in order to persist it locally for future use.
So now we are able to use OAuth Web flows for desktop applications. In the best of the worlds, every service provider may provide a real desktop flow to be used without the need to create this additional web application. In the real world, it is not the case but as you see it can be bypassed quite easily.
I will provide more technical details on the second section ‘Create a Web application’ with real sample and code in the next weeks.
In: Uncategorized
9 Dec 2011
Hi dear Petals community!
Here is a big catch-up, for all who couldn't follow news on www.petalslink.com ;)
These last three months have been quite busy, with the releases of the following:
Petals Studio 1.2: New and fresh, with lots of improvments and features, and compatibility with latest component updates! All info and links here or get straight to the download.
Petals ESB 4 Preview: a milestone of Petals ESB 4 has been released. Get a peek on next major edition of Petals ESB!
Petals Components and Dev Kit: BC-SOAP and SE-POJO have been updated, as well as our Component Development Kit.
Petals BPM: discover our latest asset in SOA infrastructure and management! Petals BPM brings business process design through a light and slick GUI!
Stay tuned! Our new service persistence component, SE-ASE, and release of Petals ESB 4, are coming soon!
Your Petals team