diff --git a/openbis_knime/.classpath b/openbis_knime/.classpath
index 8e08285d5bf6a384f9958c1b8a6db2a883696592..c3513cd8d96a27277f0a19d100e987639f9a0a06 100644
--- a/openbis_knime/.classpath
+++ b/openbis_knime/.classpath
@@ -2,9 +2,17 @@
 <classpath>
 	<classpathentry kind="src" path="source/java"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
-	<classpathentry kind="lib" path="/libraries/knime/knime-base.jar"/>
-	<classpathentry kind="lib" path="/libraries/knime/knime-core.jar"/>
+	<classpathentry kind="lib" path="/libraries/knime/knime-base.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:platform:/resource/libraries/knime/knime_2.1.2_API.zip!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="lib" path="/libraries/knime/knime-core.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:platform:/resource/libraries/knime/knime_2.1.2_API.zip!/"/>
+		</attributes>
+	</classpathentry>
 	<classpathentry kind="lib" path="/libraries/openbis-apis/query/openbis-query-api.jar"/>
-	<classpathentry kind="lib" path="/libraries/log4j/log4j.jar" sourcepath="/libraries/log4j/src.zip"/>
+	<classpathentry kind="lib" path="/libraries/cisd-base/cisd-base.jar" sourcepath="/libraries/cisd-base/cisd-base-src.zip"/>
 	<classpathentry kind="output" path="targets/classes"/>
 </classpath>
diff --git a/openbis_knime/dist/plugin.xml b/openbis_knime/dist/plugin.xml
index c2ef97692956e37673f7942f14fed7b6d523aa3c..b4a1f0bff8e6ff0a830010ce483e9f0d103d79e2 100644
--- a/openbis_knime/dist/plugin.xml
+++ b/openbis_knime/dist/plugin.xml
@@ -3,12 +3,13 @@
 
 <plugin>
    <extension point="org.knime.workbench.repository.nodes">
-      <node category-path="/openbis" factory-class="ch.systemsx.cisd.openbis.knime.TestNodeFactory" 
-            id="ch.systemsx.cisd.openbis.knime.node"/>
+      <node category-path="/openbis/query" factory-class="ch.systemsx.cisd.openbis.knime.query.QueryNodeFactory" 
+            id="ch.systemsx.cisd.openbis.knime.query.QueryNodeFactory"/>
    </extension>
    
    <extension point="org.knime.workbench.repository.categories">
       <category icon="icons/openbis.png" level-id="openbis" name="openBIS" path="/"/>
+      <category icon="icons/openbis.png" level-id="query" name="Query" path="/openbis"/>
    </extension>
    
 </plugin>
\ No newline at end of file
diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeDialog.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeDialog.java
deleted file mode 100644
index f06e6eeb620c856380872c2910e8fc9cb35e1a99..0000000000000000000000000000000000000000
--- a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeDialog.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2010 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.openbis.knime;
-
-import java.awt.BorderLayout;
-import java.awt.GridLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.List;
-
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JPasswordField;
-import javax.swing.JTextField;
-
-import org.apache.log4j.Logger;
-import org.knime.core.node.InvalidSettingsException;
-import org.knime.core.node.NodeDialogPane;
-import org.knime.core.node.NodeSettingsRO;
-import org.knime.core.node.NodeSettingsWO;
-import org.knime.core.node.NotConfigurableException;
-import org.knime.core.node.port.PortObjectSpec;
-
-import ch.systemsx.cisd.openbis.plugin.query.client.api.v1.QueryApiFacade;
-import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryDescription;
-
-/**
- * 
- *
- * @author Franz-Josef Elmer
- */
-public class TestNodeDialog extends NodeDialogPane
-{
-    private JTextField urlField;
-    private JTextField userField;
-    private JPasswordField passwordField;
-    private JComboBox queryComboBox;
-
-    TestNodeDialog()
-    {
-        super();
-        addTab("openBIS Settings", createGUI());
-    }
-
-    private JPanel createGUI()
-    {
-        JPanel panel = new JPanel(new BorderLayout());
-        JPanel form = new JPanel(new GridLayout(0, 2));
-        form.add(new JLabel("openBIS URL:"));
-        urlField = new JTextField();
-        form.add(urlField);
-        form.add(new JLabel("User:"));
-        userField = new JTextField();
-        form.add(userField);
-        form.add(new JLabel("Password:"));
-        passwordField = new JPasswordField();
-        form.add(passwordField);
-        form.add(new JLabel("Queries:"));
-        queryComboBox = new JComboBox();
-        form.add(queryComboBox);
-        panel.add(form, BorderLayout.NORTH);
-        JButton button = new JButton("connect");
-        button.addActionListener(new ActionListener()
-            {
-                
-                public void actionPerformed(ActionEvent e)
-                {
-                    QueryApiFacade facade = QueryApiFacade.create(urlField.getText(), userField.getText(), passwordField.getText());
-                    List<QueryDescription> queries = facade.listQueries();
-                    for (QueryDescription queryDescription : queries)
-                    {
-                        queryComboBox.addItem(queryDescription.getName());
-                    }
-                    // TODO Auto-generated method stub
-                    
-                }
-            });
-        panel.add(button, BorderLayout.SOUTH);
-        return panel;
-    }
-
-    @Override
-    protected void loadSettingsFrom(NodeSettingsRO settings, PortObjectSpec[] specs)
-            throws NotConfigurableException
-    {
-    }
-
-    @Override
-    protected void saveSettingsTo(NodeSettingsWO settings) throws InvalidSettingsException
-    {
-        // TODO Auto-generated method stub
-
-    }
-
-}
diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.xml b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.xml
deleted file mode 100644
index 8128aed79d12698473e73cc68a9feafe8a046942..0000000000000000000000000000000000000000
--- a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE knimeNode PUBLIC "-//UNIKN//DTD KNIME Node 2.0//EN" "http://www.knime.org/Node.dtd">
-<knimeNode icon="./openbis.png" type="Source">
-    <name>openBIS Test</name>
-    
-    <shortDescription>
-        openBIS test node
-    </shortDescription>
-    
-    <fullDescription>
-        <intro>Just testing a very simple node.        
-        </intro>
-        
-        
-        <option name="short name of first option (like in the dialog)">has no first option</option>
-        <option name="short name of second option (like in the dialog)">has no second option</option>
-    </fullDescription>
-    
-    <ports>
-        <inPort index="0" name="First In Port">Actual there are no in ports I guess</inPort>
-        <outPort index="0" name="First out Port">A simple table</outPort>
-    </ports>    
-    <views>
-        <view index="0" name="name of first view">Description of first view...</view>
-    </views>
-</knimeNode>
diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeModel.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeModel.java
deleted file mode 100644
index ba1e739538afe25f032883a44f2d00bb14dde98d..0000000000000000000000000000000000000000
--- a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeModel.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2010 ETH Zuerich, CISD
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ch.systemsx.cisd.openbis.knime;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.knime.core.data.DataTableSpec;
-import org.knime.core.data.DataType;
-import org.knime.core.data.def.DefaultRow;
-import org.knime.core.data.def.StringCell;
-import org.knime.core.node.BufferedDataContainer;
-import org.knime.core.node.BufferedDataTable;
-import org.knime.core.node.CanceledExecutionException;
-import org.knime.core.node.ExecutionContext;
-import org.knime.core.node.ExecutionMonitor;
-import org.knime.core.node.InvalidSettingsException;
-import org.knime.core.node.NodeModel;
-import org.knime.core.node.NodeSettingsRO;
-import org.knime.core.node.NodeSettingsWO;
-
-/**
- * 
- *
- * @author Franz-Josef Elmer
- */
-public class TestNodeModel extends NodeModel
-{
-
-    protected TestNodeModel()
-    {
-        super(0, 1);
-    }
-
-    @Override
-    protected void loadInternals(File arg0, ExecutionMonitor arg1) throws IOException,
-            CanceledExecutionException
-    {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    protected void loadValidatedSettingsFrom(NodeSettingsRO arg0) throws InvalidSettingsException
-    {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    protected void reset()
-    {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    protected void saveInternals(File arg0, ExecutionMonitor arg1) throws IOException,
-            CanceledExecutionException
-    {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    protected void saveSettingsTo(NodeSettingsWO arg0)
-    {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    protected void validateSettings(NodeSettingsRO arg0) throws InvalidSettingsException
-    {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    protected BufferedDataTable[] execute(BufferedDataTable[] inData, ExecutionContext exec)
-            throws Exception
-    {
-        BufferedDataContainer container = exec.createDataContainer(new DataTableSpec(new String[] {"col1", "col2"}, 
-                new DataType[] {StringCell.TYPE, StringCell.TYPE}));
-        for (int i = 0; i < 5; i++)
-        {
-            container.addRowToTable(new DefaultRow("row-"+i, "a-"+i, "b-"+i));
-        }
-        container.close();
-        return new BufferedDataTable[] {container.getTable()};
-    }
-    
-    @Override
-    protected DataTableSpec[] configure(final DataTableSpec[] inSpecs)
-            throws InvalidSettingsException
-    {
-        return new DataTableSpec[0];
-    }
-}
diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/ParameterBindings.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/ParameterBindings.java
new file mode 100644
index 0000000000000000000000000000000000000000..6616201802297ea3b497bc7677e3d11c31fb69cd
--- /dev/null
+++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/ParameterBindings.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.knime.query;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.knime.core.node.InvalidSettingsException;
+import org.knime.core.node.NodeSettingsRO;
+import org.knime.core.node.NodeSettingsWO;
+
+import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+class ParameterBindings
+{
+    static final String PARAMETER_KEYS_KEY = "query-parameter-keys";
+    static final String PARAMETER_VALUES_KEY = "query-parameter-values";
+
+    private Map<String, String> bindings = new LinkedHashMap<String, String>();
+    
+    void removeAllBindings()
+    {
+        bindings.clear();
+    }
+    
+    void bind(String parameter, String value)
+    {
+        bindings.put(parameter, value);
+    }
+    
+    Map<String, String> getBindings()
+    {
+        return bindings;
+    }
+    
+    String tryToGetBinding(String parameter)
+    {
+        return bindings.get(parameter);
+    }
+
+    void loadValidatedSettingsFrom(NodeSettingsRO settings)
+    {
+        String[] parameterKeys;
+        String[] parameterValues;
+        try
+        {
+            parameterKeys = settings.getStringArray(PARAMETER_KEYS_KEY);
+            parameterValues = settings.getStringArray(PARAMETER_VALUES_KEY);
+        } catch (InvalidSettingsException ex)
+        {
+            throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+        }
+        bindings.clear();
+        for (int i = 0, n = Math.min(parameterKeys.length, parameterValues.length); i < n; i++)
+        {
+            bindings.put(parameterKeys[i], parameterValues[i]);
+        }
+    }
+    
+    void saveSettingsTo(NodeSettingsWO settings)
+    {
+        List<String> parameterKeys = new ArrayList<String>(bindings.size());
+        List<String> parameterValues = new ArrayList<String>(bindings.size());
+        Set<Entry<String, String>> entrySet = bindings.entrySet();
+        for (Entry<String, String> entry : entrySet)
+        {
+            parameterKeys.add(entry.getKey());
+            parameterValues.add(entry.getValue());
+        }
+        settings.addStringArray(PARAMETER_KEYS_KEY, parameterKeys.toArray(new String[0]));
+        settings.addStringArray(PARAMETER_VALUES_KEY, parameterValues.toArray(new String[0]));
+    }
+}
diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeDialog.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..91cc59b63409648bafe15d2e517c2f02e8380fd1
--- /dev/null
+++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeDialog.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.knime.query;
+
+import static ch.systemsx.cisd.openbis.knime.query.QueryNodeModel.PASSWORD_KEY;
+import static ch.systemsx.cisd.openbis.knime.query.QueryNodeModel.QUERY_DESCRIPTION_KEY;
+import static ch.systemsx.cisd.openbis.knime.query.QueryNodeModel.URL_KEY;
+import static ch.systemsx.cisd.openbis.knime.query.QueryNodeModel.USER_KEY;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+
+import org.knime.core.node.InvalidSettingsException;
+import org.knime.core.node.NodeDialogPane;
+import org.knime.core.node.NodeLogger;
+import org.knime.core.node.NodeSettingsRO;
+import org.knime.core.node.NodeSettingsWO;
+import org.knime.core.node.NotConfigurableException;
+import org.knime.core.node.port.PortObjectSpec;
+
+import ch.systemsx.cisd.openbis.plugin.query.client.api.v1.FacadeFactory;
+import ch.systemsx.cisd.openbis.plugin.query.client.api.v1.IQueryApiFacade;
+import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryDescription;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public class QueryNodeDialog extends NodeDialogPane
+{
+    private static final NodeLogger log = NodeLogger.getLogger(QueryNodeDialog.class);
+    
+    private JTextField urlField;
+    private JTextField userField;
+    private JPasswordField passwordField;
+    private JComboBox queryComboBox;
+    private JPanel parametersPanel;
+    private ParameterBindings parameterBindings = new ParameterBindings();
+    private Map<String, JTextField> parameterFields = new HashMap<String, JTextField>();
+
+    QueryNodeDialog()
+    {
+        super();
+        addTab("Query Settings", createGUI());
+    }
+    
+    private JComponent createGUI()
+    {
+        JPanel panel = new JPanel(new BorderLayout());
+        panel.setPreferredSize(new Dimension(400, 450));
+        JPanel connectionPanel = new JPanel(new GridBagLayout());
+        connectionPanel.setBorder(BorderFactory.createTitledBorder("Connection Parameters"));
+        urlField = addField(connectionPanel, "openBIS URL", new JTextField(20));
+        userField = addField(connectionPanel, "User", new JTextField(20));
+        passwordField = addField(connectionPanel, "Password", new JPasswordField(20));
+        JButton button = new JButton("connect");
+        button.addActionListener(new ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    connectToOpenBIS();
+                }
+            });
+        connectionPanel.add(button, createLast());
+        panel.add(connectionPanel, BorderLayout.NORTH);
+        JPanel queryPanel = new JPanel(new BorderLayout());
+        panel.add(queryPanel, BorderLayout.CENTER);
+        queryComboBox = new JComboBox();
+        queryComboBox.addItemListener(new ItemListener()
+            {
+                public void itemStateChanged(ItemEvent e)
+                {
+                    QueryDescription queryDescription = (QueryDescription) e.getItem();
+                    updateParametersPanel(queryDescription);
+                    log.info(queryDescription);
+                }
+            });
+        JPanel querySelectionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+        querySelectionPanel.add(new JLabel("Query:"));
+        querySelectionPanel.add(queryComboBox);
+        queryPanel.add(querySelectionPanel, BorderLayout.NORTH);
+        parametersPanel = new JPanel(new GridLayout(0, 2));
+        parametersPanel.setBorder(BorderFactory.createTitledBorder("Query Parameters"));
+        JPanel northPanel = new JPanel(new BorderLayout());
+        northPanel.add(parametersPanel, BorderLayout.NORTH);
+        queryPanel.add(northPanel, BorderLayout.CENTER);
+        JScrollPane scrollPane = new JScrollPane(panel);
+        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+        return scrollPane;
+    }
+
+    @Override
+    protected void loadSettingsFrom(NodeSettingsRO settings, PortObjectSpec[] specs)
+            throws NotConfigurableException
+    {
+        urlField.setText(settings.getString(URL_KEY, ""));
+        userField.setText(settings.getString(USER_KEY, ""));
+        passwordField.setText(settings.getString(PASSWORD_KEY, ""));
+        byte[] bytes = settings.getByteArray(QUERY_DESCRIPTION_KEY, null);
+        QueryDescription queryDescriptionOrNull = Util.deserializeQueryDescription(bytes);
+        parameterBindings.loadValidatedSettingsFrom(settings);
+        if (queryDescriptionOrNull != null && queryComboBox.getItemCount() == 0)
+        {
+            queryComboBox.addItem(queryDescriptionOrNull);
+            queryComboBox.setSelectedIndex(0);
+        }
+    }
+
+    @Override
+    protected void saveSettingsTo(NodeSettingsWO settings) throws InvalidSettingsException
+    {
+        settings.addString(URL_KEY, urlField.getText().trim());
+        settings.addString(USER_KEY, userField.getText().trim());
+        settings.addString(PASSWORD_KEY, passwordField.getText().trim());
+        byte[] bytes = Util.serializeQueryDescription(getSelectedQueryDescriptionOrNull());
+        settings.addByteArray(QUERY_DESCRIPTION_KEY, bytes);
+        parameterBindings.removeAllBindings();
+        Set<Entry<String, JTextField>> entrySet = parameterFields.entrySet();
+        for (Entry<String, JTextField> entry : entrySet)
+        {
+            parameterBindings.bind(entry.getKey(), entry.getValue().getText());
+        }
+        parameterBindings.saveSettingsTo(settings);
+    }
+
+    private QueryDescription getSelectedQueryDescriptionOrNull()
+    {
+        Object selectedItem = queryComboBox.getSelectedItem();
+        return selectedItem == null ? null : (QueryDescription) selectedItem;
+    }
+
+    private <T extends JComponent> T addField(JPanel panel, String label, T field)
+    {
+        panel.add(new JLabel(label + ":"), createFirst());
+        panel.add(field, createLast());
+        return field;
+    }
+
+    private GridBagConstraints createLast()
+    {
+        GridBagConstraints last = createFirst(); 
+        last.gridwidth = GridBagConstraints.REMAINDER;
+        return last;
+    }
+    
+    private GridBagConstraints createFirst()
+    {
+        GridBagConstraints constraints = new GridBagConstraints(); 
+        constraints.anchor = GridBagConstraints.WEST; 
+        constraints.fill = GridBagConstraints.HORIZONTAL; 
+        constraints.insets = new Insets(2, 3, 2, 3);
+        return constraints;
+    }
+    
+    private void connectToOpenBIS()
+    {
+        String url = urlField.getText();
+        String userID = userField.getText();
+        String password = passwordField.getText();
+        IQueryApiFacade facade = FacadeFactory.create(url, userID, password);
+        List<QueryDescription> queries = facade.listQueries();
+        Collections.sort(queries, new Comparator<QueryDescription>()
+            {
+                public int compare(QueryDescription d1, QueryDescription d2)
+                {
+                    return d1.getName().compareTo(d2.getName());
+                }
+            });
+        QueryDescription selectedQueryDescription = getSelectedQueryDescriptionOrNull();
+        queryComboBox.removeAllItems();
+        for (QueryDescription queryDescription : queries)
+        {
+            queryComboBox.addItem(queryDescription);
+            if (queryDescription.equals(selectedQueryDescription))
+            {
+                queryComboBox.setSelectedItem(queryDescription);
+            }
+        }
+    }
+
+    private void updateParametersPanel(QueryDescription queryDescription)
+    {
+        log.info("update parameters panel for '" + queryDescription + "' which has "
+                + queryDescription.getParameters().size() + " parameters.");
+        parametersPanel.removeAll();
+        parameterFields.clear();
+        List<String> parameters = queryDescription.getParameters();
+        parametersPanel.setVisible(parameters.isEmpty() == false);
+        for (String parameter : parameters)
+        {
+            JTextField field = parameterFields.get(parameter);
+            if (field == null)
+            {
+                field = new JTextField(15);
+                parameterFields.put(parameter, field);
+            }
+            String value = parameterBindings.tryToGetBinding(parameter);
+            if (value != null)
+            {
+                field.setText(value);
+            }
+            addField(parametersPanel, parameter, field);
+        }
+        parametersPanel.invalidate();
+        parametersPanel.getParent().validate();
+    }
+    
+
+}
diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.java
similarity index 77%
rename from openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.java
rename to openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.java
index daa77002197ca8176aac96c8c8f3bbdda80efc02..d10a56ce721bea47aff9d509c1e5ef2f5e4b547a 100644
--- a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/TestNodeFactory.java
+++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.openbis.knime;
+package ch.systemsx.cisd.openbis.knime.query;
 
 import org.knime.core.node.NodeDialogPane;
 import org.knime.core.node.NodeFactory;
@@ -25,23 +25,23 @@ import org.knime.core.node.NodeView;
  *
  * @author Franz-Josef Elmer
  */
-public class TestNodeFactory extends NodeFactory<TestNodeModel>
+public class QueryNodeFactory extends NodeFactory<QueryNodeModel>
 {
 
     @Override
     protected NodeDialogPane createNodeDialogPane()
     {
-        return new TestNodeDialog();
+        return new QueryNodeDialog();
     }
 
     @Override
-    public TestNodeModel createNodeModel()
+    public QueryNodeModel createNodeModel()
     {
-        return new TestNodeModel();
+        return new QueryNodeModel();
     }
 
     @Override
-    public NodeView<TestNodeModel> createNodeView(int arg0, TestNodeModel arg1)
+    public NodeView<QueryNodeModel> createNodeView(int viewIndex, QueryNodeModel model)
     {
         return null;
     }
diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.xml b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.xml
new file mode 100644
index 0000000000000000000000000000000000000000..85a654551c6f5d60d5890317be9cc0a1d9e0cfc0
--- /dev/null
+++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeFactory.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE knimeNode PUBLIC "-//UNIKN//DTD KNIME Node 2.0//EN" "http://www.knime.org/Node.dtd">
+<knimeNode icon="./openbis.png" type="Source">
+    <name>openBIS Query Reader</name>
+    
+    <shortDescription>openBIS query node</shortDescription>
+    
+    <fullDescription>
+        <intro>Data source node to run a parameterized SQL query on openBIS Application Server  
+        </intro>
+    </fullDescription>
+    
+    <ports>
+        <outPort index="0" name="Result Set">Table with result set</outPort>
+    </ports>    
+</knimeNode>
diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeModel.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..bdb3ae5bf7d3a709d09f403d2d2b1244b0f89c4c
--- /dev/null
+++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/QueryNodeModel.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.knime.query;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.List;
+
+import org.knime.core.data.DataCell;
+import org.knime.core.data.DataTableSpec;
+import org.knime.core.data.DataType;
+import org.knime.core.data.def.DefaultRow;
+import org.knime.core.data.def.DoubleCell;
+import org.knime.core.data.def.LongCell;
+import org.knime.core.data.def.StringCell;
+import org.knime.core.node.BufferedDataContainer;
+import org.knime.core.node.BufferedDataTable;
+import org.knime.core.node.CanceledExecutionException;
+import org.knime.core.node.ExecutionContext;
+import org.knime.core.node.ExecutionMonitor;
+import org.knime.core.node.InvalidSettingsException;
+import org.knime.core.node.NodeModel;
+import org.knime.core.node.NodeSettingsRO;
+import org.knime.core.node.NodeSettingsWO;
+
+import ch.systemsx.cisd.openbis.plugin.query.client.api.v1.FacadeFactory;
+import ch.systemsx.cisd.openbis.plugin.query.client.api.v1.IQueryApiFacade;
+import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryDescription;
+import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryTableColumn;
+import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryTableModel;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public class QueryNodeModel extends NodeModel
+{
+    static final String URL_KEY = "url";
+    static final String USER_KEY = "user";
+    static final String PASSWORD_KEY = "password";
+    static final String QUERY_DESCRIPTION_KEY = "query-description";
+    
+    private String url;
+    private String userID;
+    private String password;
+    private QueryDescription queryDescription;
+    private ParameterBindings parameterBindings = new ParameterBindings();
+
+    protected QueryNodeModel()
+    {
+        super(0, 1);
+    }
+    
+    @Override
+    protected DataTableSpec[] configure(final DataTableSpec[] inSpecs)
+            throws InvalidSettingsException
+    {
+        return new DataTableSpec[1];
+    }
+
+    @Override
+    protected void validateSettings(NodeSettingsRO settings) throws InvalidSettingsException
+    {
+    }
+    
+    @Override
+    protected void loadValidatedSettingsFrom(NodeSettingsRO settings) throws InvalidSettingsException
+    {
+        url = settings.getString(URL_KEY);
+        userID = settings.getString(USER_KEY);
+        password = settings.getString(PASSWORD_KEY);
+        queryDescription = Util.deserializeQueryDescription(settings.getByteArray(QUERY_DESCRIPTION_KEY));
+        parameterBindings.loadValidatedSettingsFrom(settings);
+    }
+
+    @Override
+    protected void saveSettingsTo(NodeSettingsWO settings)
+    {
+        settings.addString(URL_KEY, url);
+        settings.addString(USER_KEY, userID);
+        settings.addString(PASSWORD_KEY, password);
+        settings.addByteArray(QUERY_DESCRIPTION_KEY, Util
+                .serializeQueryDescription(queryDescription));
+        parameterBindings.saveSettingsTo(settings);
+    }
+    
+    @Override
+    protected void reset()
+    {
+    }
+
+    @Override
+    protected void saveInternals(File arg0, ExecutionMonitor arg1) throws IOException,
+            CanceledExecutionException
+    {
+    }
+
+    @Override
+    protected void loadInternals(File arg0, ExecutionMonitor arg1) throws IOException,
+    CanceledExecutionException
+    {
+    }
+    
+    @Override
+    protected BufferedDataTable[] execute(BufferedDataTable[] inData, ExecutionContext exec)
+            throws Exception
+    {
+        IQueryApiFacade facade = createFacade(url, userID, password);
+        QueryTableModel result = facade.executeQuery(queryDescription.getId(), parameterBindings.getBindings());
+        List<QueryTableColumn> columns = result.getColumns();
+        String[] columnTitles = new String[columns.size()];
+        DataType[] columnTypes = new DataType[columns.size()];
+        for (int i = 0, n = columns.size(); i < n; i++)
+        {
+            QueryTableColumn column = columns.get(i);
+            columnTitles[i] = column.getTitle();
+            columnTypes[i] = Util.translateDataType(column.getDataType());
+        }
+        DataTableSpec dataTableSpec = new DataTableSpec(columnTitles, columnTypes);
+        BufferedDataContainer container = exec.createDataContainer(dataTableSpec);
+        List<Serializable[]> rows = result.getRows();
+        for (int i = 0, n = rows.size(); i < n; i++)
+        {
+            Serializable[] row = rows.get(i);
+            DataCell[] cells = new DataCell[row.length];
+            for (int c = 0; c < row.length; c++)
+            {
+                Serializable value = row[c];
+                DataCell cell = null;
+                if (value instanceof Double)
+                {
+                    cell = new DoubleCell((Double) value);
+                } else if (value instanceof Long)
+                {
+                    cell = new LongCell((Long) value);
+                } else
+                {
+                    cell = new StringCell(value.toString());
+                }
+                cells[c] = cell;
+            }
+            container.addRowToTable(new DefaultRow(Integer.toString(i), cells));
+        }
+        container.close();
+        return new BufferedDataTable[] {container.getTable()};
+    }
+    
+    protected IQueryApiFacade createFacade(String serverURL, String user, String psswrd)
+    {
+       return FacadeFactory.create(serverURL, user, psswrd); 
+    }
+
+}
diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/Util.java b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/Util.java
new file mode 100644
index 0000000000000000000000000000000000000000..02023d45fca50f3b3a3df2dd70a19b0cb1c0b09e
--- /dev/null
+++ b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/Util.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.knime.query;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.knime.core.data.DataType;
+import org.knime.core.data.def.DoubleCell;
+import org.knime.core.data.def.LongCell;
+import org.knime.core.data.def.StringCell;
+
+import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryDescription;
+import ch.systemsx.cisd.openbis.plugin.query.shared.api.v1.dto.QueryTableColumnDataType;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+class Util
+{
+    static byte[] serializeQueryDescription(QueryDescription queryDescriptionOrNull)
+    {
+        if (queryDescriptionOrNull == null)
+        {
+            return null;
+        }
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try
+        {
+            new ObjectOutputStream(baos).writeObject(queryDescriptionOrNull);
+            return baos.toByteArray();
+        } catch (IOException ex)
+        {
+            return null;
+        }
+    }
+    
+    static QueryDescription deserializeQueryDescription(byte[] serializeQueryDescriptionOrNull)
+    {
+        if (serializeQueryDescriptionOrNull == null)
+        {
+            return null;
+        }
+        ByteArrayInputStream bais = new ByteArrayInputStream(serializeQueryDescriptionOrNull);
+        try
+        {
+            return (QueryDescription) new ObjectInputStream(bais).readObject();
+        } catch (Exception ex)
+        {
+            return null;
+        }
+    }
+    
+    static DataType translateDataType(QueryTableColumnDataType dataType)
+    {
+        switch (dataType)
+        {
+            case DOUBLE: return DoubleCell.TYPE;
+            case LONG: return LongCell.TYPE;
+            default: return StringCell.TYPE;
+        }
+    }
+}
diff --git a/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/openbis.png b/openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/openbis.png
similarity index 100%
rename from openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/openbis.png
rename to openbis_knime/source/java/ch/systemsx/cisd/openbis/knime/query/openbis.png