<bundle-version>$(replace;${project.version};-SNAPSHOT;.qualifier)</bundle-version>
I'm a software architect. I'm currently working in an integration team. Managing Continous Integration and building, lightweight test framework and other support tools. With this blog i'd like to share experience and receive others's feeling.
Tuesday, October 22, 2013
OSGI Maven bundle for Eclipse (Part 2)
In a previous post I use maven-bundle plugin to expose maven artifact as OSGI bundle.
I change a little my approach and now update the classpath manually.
After using this setup for a while, I experiment one problem : How to convert maven plugin version including -SNAPSHOT to .qualifier ?
After many search I found a solution using BND macro.
You "just" have to put in "Bundle-Version" this macro :
Wednesday, October 9, 2013
Sharing source through usb key and git
Aims :
Set up a git environment with for two desktops sharing source code through USB
Warning : all those commands have to be tested before use. Check git documentation for more explanations.
using git-bash, in the repository folder do
using git-bash, in the source folder do
create a .gitignore
Add a remote repository (assuming the drive is f)
Push sources
pull sources
if you want to overide local changes
at this point local untrack file and dir still exists (see git clean)
Set up a git environment with for two desktops sharing source code through USB
Warning : all those commands have to be tested before use. Check git documentation for more explanations.
git env creation on USB Key
using git-bash, in the repository folder do
$ git --bare init
git env creation on one desktop
using git-bash, in the source folder do
$ git init
manage ignored ressourcescreate a .gitignore
$ git add .gitignore
$ git commit -m "ignored resource"
avoid conversion from LF to CRLF $ git config core.autocrlf false
$ git config --global user.name "yourName"
$ git config --global user.email yourEmail
commit your existing sources$ git add --all
$ git commit -m "initial commit"
Add a remote repository (assuming the drive is f)
$ git remote add origin /f/path/to/repo/
Push sources
$ git push origin master
On the second desktop
using git-bash, in the source folder do$ git init
$ git remote add origin /f/path/to/repo/
pull sources
$ git pull origin master
Tips
if you want to overide local changes
$ git fetch origin master
$ git reset --hard FETCH_HEAD
at this point local untrack file and dir still exists (see git clean)
Tuesday, September 17, 2013
Rich editor in eclipse RCP (Part2)
A few month ago I built a rich editor for eclipse based on SWT browser.
I use this implementation from this time and now I want to integrate it in an EMF (EEF generated) GUI.
In this context this widget needs a focus managment but the SWT Browser does not manage those events (See Javadoc (event) ).
In my case I decide to rely on TyneMCE events managment (blur and focus), then react on those events invoking a BrowserFunction that allows javascript to java communication. In java side the Browser fonction notify an internal listener.
Rely on tinyMce events
those event are identified bty name : blur and focus. To be able to react to those events, add to your tiny init (JS) :
setup : function(ed) {
...
ed.onInit.add(function(ed) {
if (tinymce.isIE) {
tinymce.dom.Event.add(ed.getWin(), 'focus', function(e) {
evt_focusGained();
});
tinymce.dom.Event.add(ed.getWin(), 'blur', function(e) {
evt_focusLost();
});
} else {
tinymce.dom.Event.add(ed.getDoc(), 'focus', function(e) {
evt_focusGained();
});
tinymce.dom.Event.add(ed.getDOc(), 'blur', function(e) {
evt_focusLost();
});
}
});
},
Usage of BrowserFuntion
Browser function allow communication from javascript to java. Excerpt : "Instances of this class represent java-side "functions" that are invokable from javascript. Browser clients define these functions by subclassing
BrowserFunction
and overriding its function(Object[])
method. This method will be invoked whenever javascript running in the Browser makes a call with the function's name."So I add in the completed method of the SWT browser progressListener :
browser.addProgressListener(new ProgressListener() {
public void changed(ProgressEvent event) {
}
public void completed(ProgressEvent event) {
// used for setEditorText
completed = true;
loadEditorText((String) browser.getData("htmlcontent"));
new BrowserFunction(browser, "evt_focusLost") {
public Object function(Object[] arguments) {
notifyListenersFocusLost();
return null;
}
};
new BrowserFunction(browser, "evt_focusGained") {
public Object function(Object[] arguments) {
notifyListenersFocusGained();
return null;
}
};
}
});
In this implementation, you could see notifyListenersFocusLost() and notifyListenersFocusGained(). Those two methods relate to two listeners similar implementation.
public interface TinyFocusLostListener {
public abstract void focusLost();
}
private List listenersTinyFocusLost = new ArrayList();
public void addTinyFocusLostListener(TinyFocusLostListener listenerValue) {
listenersTinyFocusLost.add(listenerValue);
}
// Warning UI action use asyncexec in eclipse
private void notifyListenersFocusLost() {
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
for (TinyFocusLostListener listener : listenersTinyFocusLost) {
listener.focusLost();
}
}
});
}
finally on Java side
myTinyIntegrationInstance.addTinyFocusLostListener(new TinyFocusLostListener() {
@Override
public void focusLost() {
//Add your code here
}
}
});
Friday, March 22, 2013
fast bulk data insert in Mysql
Last couple of week I have to work on a persistancy component.
The problematic was :
The whole datas (not only those lists) have to be request in many ways and they are not all known, so we choose to test a relational database system to offer large type of request .
As we have a Mysql 5.0 server install we decide to use this database.
To be able to progress we define many use case. The main use cases are :
The request LOAD DATA LOCAL INFILE is specific to mysql and allows the best performance is our case (time divide by 15). We have other thing to do optimize again our request time like :
The problematic was :
- Import of huge data list ; from 500K itemes to 1.5M items
- where items are ordered and contains a date,
- and items contains 5 double.
The whole datas (not only those lists) have to be request in many ways and they are not all known, so we choose to test a relational database system to offer large type of request .
As we have a Mysql 5.0 server install we decide to use this database.
To be able to progress we define many use case. The main use cases are :
- Start from a text file containing datas (500k lines, tab separated) and Import those file in mysql
- implies convert file to object
- implies RDB INSERT request
- Read those 500k items
- implies RDB SELECT
- Write in an another place those 500k items
- implies convert SELECT result to object
- implies RDB INSERT
The last two points fake a standard process for us : get datas, process results with previous datas, and finally push result.
So we try many thing, using jdbc bridge and we progress while we read many post and article about "Fast INSERT INTO " ; The list below is show starting from the worst performance in our case to the best.
- using jdbc statment and default autocommit
- one request for one line, commit each time
- using jdbc statment , autocomit to false and then commit
- one request for one line, commit each the end of lines process
- using jdbc statment, addbatch, autocomit to false and then commit
- one request for many lines lines (we use a batch size to preserve memory and spread RDB load) , commit
- using jdbc prepareStatment and addbatch, autocomit to false and then commit
- use RDB optimization when dealing many times the same request.
- using LOAD DATA LOCAL INFILE using and ImputStream
- we convert the file in an imput stream :
- adding an order
- converting date format
- giving an extenal id
Statement stmt = con.createStatement();
String statementText = "LOAD DATA LOCAL INFILE 'file.txt' "
+ "INTO TABLE tableEntry "
+ " (date, a, b, c, d, e, idx) "
+ " SET FK_ID ="
+ getExternalId();
InputStream is = readDataAsImpuStream(source);
((com.mysql.jdbc.Statement) stmt).setLocalInfileInputStream(is);
stmt.execute(statementText);
The request LOAD DATA LOCAL INFILE is specific to mysql and allows the best performance is our case (time divide by 15). We have other thing to do optimize again our request time like :
- RBD server setting
- Modifyng table structure to reduce the number of fields
- ....
Monday, January 14, 2013
Recipes : linking EMF with CNF
How to link an EMF model instance with Common Navigator Framework:
- CNF overriding
- CNF ContentBinding with EMF
- Adding menu contribution (WIP)
- Using TransactionalEditingDomain (WIP)
Adding a view
- using org.eclipse.ui.views
<extension point="org.eclipse.ui.views">
<category
id="francky.newproject.categoryview"
name="New Project">
</category>
<view
allowMultiple="false"
category="francky.newproject.categoryview"
class="francky.newproject.NewNavigator"
icon="icons/obj16/Project-nature.gif"
id="francky.newproject.navigatorView"
name="New Navigator"
restorable="true">
</view>
</extension>
the class extend CNF the navigator
public class NewNavigator extends CommonNavigator implements CommandStackListener {
//...
}
Define Content
- defining content and filter
<!-- NAVIGATOR CONTENT-->
<extension point="org.eclipse.ui.navigator.navigatorContent">
<navigatorContent
activeByDefault="true"
contentProvider="francky.newproject.providers.NewProjectContentProvider"
icon="icons/obj16/Project-nature.gif"
id="francky.newproject.navigatorContent"
labelProvider="francky.newproject.providers.NewProjectLabelProvider"
name="New project content"
priority="normal">
<triggerPoints>
<and>
<instanceof value="org.eclipse.core.resources.IResource">
</instanceof>
<test forcePluginActivation="true"
property="org.eclipse.core.resources.extension"
value="frk">
</test>
</and>
</triggerPoints>
<possibleChildren>
<or>
<instanceof value="org.eclipse.emf.ecore.resource.Resource"/>
<instanceof value="org.eclipse.emf.ecore.EObject"/>
</or>
</possibleChildren>
</navigatorContent>
</extension>
<!-- CONTENT FILTER -->
<extension point="org.eclipse.ui.navigator.navigatorContent">
<commonFilter
activeByDefault="true"
id="francky.newproject.filters.hideNonNewProject"
name="Hide Non New Project"
visibleInUI="true">
<filterExpression>
<and>
<not>
<adapt
type="org.eclipse.core.resources.IProject">
<test
property="org.eclipse.core.resources.projectNature"
value="francky.newproject.NewNature">
</test>
</adapt>
</not>
<not>
<instanceof
value="org.eclipse.core.resources.IFolder">
</instanceof>
</not>
<not>
<and>
<instanceof value="org.eclipse.core.resources.IResource">
</instanceof>
<!-- EMF instance file extension is frk -->
<test forcePluginActivation="true"
property="org.eclipse.core.resources.extension"
value="frk">
</test>
</and>
</not>
<not>
<instanceof value="org.eclipse.emf.ecore.resource.Resource"/>
</not>
<not>
<instanceof value="org.eclipse.emf.ecore.EObject"/>
</not>
</and>
</filterExpression>
</commonFilter>
</extension>
<!-- REGISTER CONTENT AND FILTER-->
<extension point="org.eclipse.ui.navigator.viewer">
<viewer
viewerId="francky.newproject.navigatorView">
</viewer>
<viewerContentBinding viewerId="francky.newproject.navigatorView">
<includes>
<contentExtension pattern="org.eclipse.ui.navigator.resourceContent"/>
<contentExtension pattern="org.eclipse.ui.navigator.resources.filters.*"/>
<contentExtension pattern="francky.newproject.filters.*"/>
<contentExtension pattern="francky.newproject.navigatorContent"/>
</includes>
</viewerContentBinding>
<viewerActionBinding viewerId="francky.newproject.navigatorView">
<includes>
<actionExtension pattern="org.eclipse.ui.navigator.resources.*"/>
</includes>
</viewerActionBinding>
</extension>
Define content and label provider
- Defining content provider using adapterFactories
public class NewAdapterFactory
{
private static ComposedAdapterFactory NewAdapterFactory;
public final static ComposedAdapterFactory getAdapterFactory()
{
if (NewAdapterFactory == null)
NewAdapterFactory = new ComposedAdapterFactory(createFactoryList());
return NewAdapterFactory;
}
public final static ArrayList<AdapterFactory> createFactoryList()
{
ArrayList<AdapterFactory> factories = new ArrayList<AdapterFactory>();
factories.add(new ResourceItemProviderAdapterFactory());
//Add your AAAItemProviderAdapterFactory here....
factories.add(new InfratestItemProviderAdapterFactory());
factories.add(new ReflectiveItemProviderAdapterFactory());
return factories;
}
}
Label provider
public class NewProjectLabelProvider extends AdapterFactoryLabelProvider {
public NewProjectLabelProvider() {
super(NewAdapterFactory.getAdapterFactory());
}
public Image getImage(Object element) {
return super.getImage(element);
}
public String getText(Object element) {
return super.getText(element);
}
}
Content provider
public class NewProjectContentProvider extends
AdapterFactoryContentProvider implements IResourceChangeListener,
IResourceDeltaVisitor {
private static ResourceSetImpl resourceSet = new ResourceSetImpl();
public NewProjectContentProvider() {
super(NewAdapterFactory.getAdapterFactory());
ResourcesPlugin.getWorkspace().addResourceChangeListener(this,
IResourceChangeEvent.POST_CHANGE);
}
...
Wednesday, January 9, 2013
Eclispse :creating a project with specific nature
Recipes for creating a project with specific nature
Here I put the main piece of code for eclipse project creation with nature management.
Create a project nature
in an eclipse plugin add adependency on- org.eclipse.core.resource
Create your own class nature
- public class NewNature implements IProjectNature
- add an attribute nature_id
public class NewNature implements IProjectNature {
public static final String NATURE_ID = "francky.newproject.NewNature";
private IProject project;
@Override
public void configure() throws CoreException {
// TODO Auto-generated method stub
}
@Override
public void deconfigure() throws CoreException {
}
@Override
public IProject getProject() {
return project;
}
@Override
public void setProject(IProject project) {
this.project =project;
}
}
Declare an extension point
- relying on : org.eclipse.core.resources.natures
<extension
id="NewNature"
name="New nature Project"
point="org.eclipse.core.resources.natures">
<runtime>
<run
class="francky.newProject.nature.NewNature">
</run>
</runtime>
</extension>
- give it the right nature id
- set the target class NewNature
Add configure, de-configure menunature
- relying on : org.eclipse.ui.popupMenus
<extension point="org.eclipse.ui.popupMenus">
<objectContribution
adaptable="true"
id="francky.newProject.enableNatureAction"
objectClass="org.eclipse.core.resources.IProject">
<action
class="francky.newProject.actions.EnableNatureAction"
enablesFor="+"
id="francky.newProject.action.enableNatureAction"
label="Enable new nature"
menubarPath="org.eclipse.ui.projectConfigure/additions"
style="push">
</action>
<visibility>
<and>
<objectState name="open" value="true"/>
<not>
<objectState name="nature" value="francky.newProject.NewNature"/>
</not>
</and>
</visibility>
</objectContribution>
Adding a wizard for Project creation
- relying on : org.eclipse.ui.newWizards
<extension
point="org.eclipse.ui.newWizards">
<category
id="francky.newProject.category"
name="New global Project">
</category>
<wizard
category="francky.newProject.category"
class="francky.newProject.template.CreatePluginProjectWizard"
icon="icons/obj16/Project-nature.gif"
id="francky.newProject.NewProjectWizard"
name="New Project"
project="true">
</wizard>
</extension>
- and relying on the francky.newproject.NewProjectWizard methods performFinish :
public boolean performFinish() {
final Set<String> requiredBundles = new HashSet<String>();
requiredBundles.add("org.eclipse.core.runtime");
final List<String> exportedPackages = null;
final Shell theShell = getShell();
final List<IProject> referencedProjects = new ArrayList<IProject>();
final List<String> srcFolders = new ArrayList<String>();
srcFolders.add("src");
final List<String> extraFolders = new ArrayList<String>();
extraFolders.add("model");
final String projectName = page.getProjectName();
IRunnableWithProgress operation = new IRunnableWithProgress() {
public void run(final IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
try {
//See below
EclipseHelper.createProject(projectName,
srcFolders,extraFolders,
referencedProjects, requiredBundles,
exportedPackages, monitor, theShell);
} catch (Exception e) {
throw new InvocationTargetException(e);
}
}
};
try {
new ProgressMonitorDialog(getShell()).run(true, true, operation);
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
- EclipseHelper.createProject
public static IProject createProject(final String projectName,
final List<String> srcFolders,
final List<String> extraFolders,
final List<IProject> referencedProjects,
final Set<String> requiredBundles,
final List<String> exportedPackages,
final IProgressMonitor progressMonitor,
final Shell theShell) {
IProject project = null;
try {
progressMonitor.beginTask("", 14);
progressMonitor.subTask("Creating project " + projectName);
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
project = workspace.getRoot().getProject(projectName);
// Clean up any old project information.
if (project.exists()) {
final boolean[] result = new boolean[1];
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
public void run() {
result[0] = MessageDialog.openQuestion(theShell,
"Do you want to overwrite the project "
+ projectName, "Note that everything inside the project '"
+ projectName
+ "' will be deleted if you confirm this dialog.");
}
});
if (result[0]) {
project.delete(true, true,
new SubProgressMonitor(progressMonitor, 1));
}
else
return null;
}
final IJavaProject javaProject = JavaCore.create(project);
final IProjectDescription projectDescription =
ResourcesPlugin.getWorkspace().newProjectDescription(projectName);
projectDescription.setLocation(null);
project.create(projectDescription,
new SubProgressMonitor(progressMonitor, 1));
final List<IClasspathEntry> classpathEntries =
new ArrayList<IClasspathEntry>();
if (referencedProjects.size() != 0) {
projectDescription.setReferencedProjects(
referencedProjects.toArray(
new IProject[referencedProjects.size()]));
for (final IProject referencedProject : referencedProjects) {
final IClasspathEntry referencedProjectClasspathEntry =
JavaCore.newProjectEntry(referencedProject
.getFullPath());
classpathEntries.add(referencedProjectClasspathEntry);
}
}
projectDescription.setNatureIds(new String[] {
JavaCore.NATURE_ID,
"org.eclipse.pde.PluginNature",
NewNature.NATURE_ID});
final ICommand java = projectDescription.newCommand();
java.setBuilderName(JavaCore.BUILDER_ID);
final ICommand manifest = projectDescription.newCommand();
manifest.setBuilderName("org.eclipse.pde.ManifestBuilder");
final ICommand schema = projectDescription.newCommand();
schema.setBuilderName("org.eclipse.pde.SchemaBuilder");
projectDescription.setBuildSpec(new ICommand[] { java, manifest, schema });
progressMonitor.subTask("Opening project ");
project.open(new SubProgressMonitor(progressMonitor, 1));
progressMonitor.subTask("Setting project description ");
project.setDescription(projectDescription,
new SubProgressMonitor(progressMonitor, 1));
progressMonitor.subTask("Creating source folders ");
createSrcFolders(srcFolders, progressMonitor, project,
classpathEntries);
progressMonitor.subTask("Creating extra folders ");
createExtraFolders(extraFolders, progressMonitor, project);
classpathEntries.add(JavaCore.newContainerEntry(
new Path("org.eclipse.jdt.launching.JRE_CONTAINER/"+
"org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/"+
J2SE-1.5")));
classpathEntries.add(JavaCore.newContainerEntry(
new Path("org.eclipse.pde.core.requiredPlugins")));
progressMonitor.subTask("Setting classpath ");
javaProject.setRawClasspath(classpathEntries.toArray(
new IClasspathEntry[classpathEntries.size()]),
new SubProgressMonitor(progressMonitor, 1));
javaProject.setOutputLocation(
new Path("/" + projectName + "/bin"),
new SubProgressMonitor(progressMonitor,
1));
progressMonitor.subTask("Creating manifest file ");
createManifest(projectName, requiredBundles, exportedPackages,
progressMonitor, project);
progressMonitor.subTask("Creating build file ");
createBuildProps(progressMonitor, project, srcFolders);
progressMonitor.subTask("Creating plugin file ");
createPluginFile(progressMonitor, project);
}
catch (final Exception exception) {
exception.printStackTrace();
//FIXME
System.out.println(exception);
}
finally {
progressMonitor.done();
}
return project;
}
Subscribe to:
Posts (Atom)