diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95d74d72a..fc13a881e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,13 +2,21 @@
 
 All notable changes to this project will be documented in this file.
 
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0). 
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0).
 
 ## 3.1.0
 
 ### Added
 
-- Extended `.phpstorm.meta.php` for more convenient autocomplete
+- Extended `.phpstorm.meta.php` for more convenient autocomplete [#467](https://github.com/magento/magento2-phpstorm-plugin/pull/467)
+- Code generation for message queue in [#411](https://github.com/magento/magento2-phpstorm-plugin/pull/411)
+- Code generation for declarative schema [#453](https://github.com/magento/magento2-phpstorm-plugin/pull/453)
+- Inspection warning for disabled observer [#432](https://github.com/magento/magento2-phpstorm-plugin/pull/432)
+- The action item to the context menu to copy file path in the Magento format [#451](https://github.com/magento/magento2-phpstorm-plugin/pull/451)
+
+### Fixed
+
+- The null pointer exception on the Create Module Dialog
 
 ## 3.0.4
 
diff --git a/README.md b/README.md
index c03a8415e..f9a9616ee 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,7 @@
 [](https://plugins.jetbrains.com/plugin/8024)
 [](https://plugins.jetbrains.com/plugin/8024)
 
+[](https://magento.com)
 
 ## Installation
 
diff --git a/resources/phpstorm.meta.php/di-autocomplete.php b/resources/.phpstorm.meta.php/di-autocomplete.php
similarity index 100%
rename from resources/phpstorm.meta.php/di-autocomplete.php
rename to resources/.phpstorm.meta.php/di-autocomplete.php
diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml
index 35d9f7eb1..e7fd64154 100644
--- a/resources/META-INF/plugin.xml
+++ b/resources/META-INF/plugin.xml
@@ -236,7 +236,6 @@
     
         
         
-        
+        
     
-
 
diff --git a/resources/fileTemplates/internal/Magento Data Model Interface.php.ft b/resources/fileTemplates/internal/Magento Data Model Interface.php.ft
index 2efe47430..efa91463e 100644
--- a/resources/fileTemplates/internal/Magento Data Model Interface.php.ft	
+++ b/resources/fileTemplates/internal/Magento Data Model Interface.php.ft	
@@ -1,6 +1,5 @@
 
 
diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewMessageQueueDialog.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewMessageQueueDialog.java
index fa108e58e..e444c0574 100644
--- a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewMessageQueueDialog.java
+++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewMessageQueueDialog.java
@@ -7,8 +7,9 @@
 
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.PsiDirectory;
-import com.magento.idea.magento2plugin.actions.generation.NewDataModelAction;
+import com.intellij.ui.DocumentAdapter;
 import com.magento.idea.magento2plugin.actions.generation.NewMessageQueueAction;
+import com.magento.idea.magento2plugin.actions.generation.data.MessageQueueClassData;
 import com.magento.idea.magento2plugin.actions.generation.data.QueueCommunicationData;
 import com.magento.idea.magento2plugin.actions.generation.data.QueueConsumerData;
 import com.magento.idea.magento2plugin.actions.generation.data.QueuePublisherData;
@@ -22,23 +23,32 @@
 import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.NotEmptyRule;
 import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.NumericRule;
 import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.PhpClassFqnRule;
+import com.magento.idea.magento2plugin.actions.generation.generator.MessageQueueClassGenerator;
 import com.magento.idea.magento2plugin.actions.generation.generator.QueueCommunicationGenerator;
 import com.magento.idea.magento2plugin.actions.generation.generator.QueueConsumerGenerator;
 import com.magento.idea.magento2plugin.actions.generation.generator.QueuePublisherGenerator;
 import com.magento.idea.magento2plugin.actions.generation.generator.QueueTopologyGenerator;
+import com.magento.idea.magento2plugin.actions.generation.generator.util.NamespaceBuilder;
+import com.magento.idea.magento2plugin.magento.files.MessageQueueClassPhp;
+import com.magento.idea.magento2plugin.magento.packages.MessageQueueConnections;
 import com.magento.idea.magento2plugin.util.magento.GetModuleNameByDirectoryUtil;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import javax.swing.JButton;
+import javax.swing.JComboBox;
 import javax.swing.JComponent;
+import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JTextField;
 import javax.swing.KeyStroke;
+import javax.swing.event.DocumentEvent;
+import org.jetbrains.annotations.NotNull;
 
 @SuppressWarnings({
         "PMD.TooManyFields",
+        "PMD.TooManyMethods",
         "PMD.ExcessiveImports",
 })
 public class NewMessageQueueDialog extends AbstractDialog {
@@ -49,11 +59,12 @@ public class NewMessageQueueDialog extends AbstractDialog {
     private static final String QUEUE_NAME = "Queue Name";
     private static final String CONSUMER_TYPE = "Consumer Type";
     private static final String MAX_MESSAGES = "Maximum Messages";
-    private static final String CONNECTION_NAME = "Connection Name";
     private static final String EXCHANGE_NAME = "Exchange Name";
     private static final String BINDING_ID = "Binding ID";
     private static final String BINDING_TOPIC = "Binding Topic";
 
+    private JComboBox connectionName;
+
     /* TODO: Improve validation */
     @FieldValidation(rule = RuleRegistry.NOT_EMPTY,
             message = {NotEmptyRule.MESSAGE, TOPIC_NAME})
@@ -65,15 +76,15 @@ public class NewMessageQueueDialog extends AbstractDialog {
 
     @FieldValidation(rule = RuleRegistry.NOT_EMPTY,
             message = {NotEmptyRule.MESSAGE, HANDLER_NAME})
-    @FieldValidation(rule = RuleRegistry.ALPHANUMERIC_WITH_UNDERSCORE,
+    @FieldValidation(rule = RuleRegistry.ALPHA_WITH_PERIOD,
             message = {AlphanumericWithUnderscoreRule.MESSAGE, HANDLER_NAME})
     private JTextField handlerName;
 
     @FieldValidation(rule = RuleRegistry.NOT_EMPTY,
             message = {NotEmptyRule.MESSAGE, HANDLER_TYPE})
-    @FieldValidation(rule = RuleRegistry.PHP_CLASS_FQN,
+    @FieldValidation(rule = RuleRegistry.PHP_CLASS,
             message = {PhpClassFqnRule.MESSAGE, HANDLER_TYPE})
-    private JTextField handlerType;
+    private JTextField handlerClass;
 
     @FieldValidation(rule = RuleRegistry.NOT_EMPTY,
             message = {NotEmptyRule.MESSAGE, CONSUMER_NAME})
@@ -93,9 +104,9 @@ public class NewMessageQueueDialog extends AbstractDialog {
 
     @FieldValidation(rule = RuleRegistry.NOT_EMPTY,
             message = {NotEmptyRule.MESSAGE, CONSUMER_TYPE})
-    @FieldValidation(rule = RuleRegistry.PHP_CLASS_FQN,
+    @FieldValidation(rule = RuleRegistry.PHP_CLASS,
             message = {PhpClassFqnRule.MESSAGE, CONSUMER_TYPE})
-    private JTextField consumerType;
+    private JTextField consumerClass;
 
     @FieldValidation(rule = RuleRegistry.NOT_EMPTY,
             message = {NotEmptyRule.MESSAGE, MAX_MESSAGES})
@@ -103,11 +114,6 @@ public class NewMessageQueueDialog extends AbstractDialog {
             message = {NumericRule.MESSAGE, MAX_MESSAGES})
     private JTextField maxMessages;
 
-    // TODO: Can this be made a dropdown?
-    @FieldValidation(rule = RuleRegistry.NOT_EMPTY,
-            message = {NotEmptyRule.MESSAGE, CONNECTION_NAME})
-    private JTextField connectionName;
-
     @FieldValidation(rule = RuleRegistry.NOT_EMPTY,
             message = {NotEmptyRule.MESSAGE, EXCHANGE_NAME})
     @FieldValidation(rule = RuleRegistry.ALPHA_WITH_DASH,
@@ -120,14 +126,25 @@ public class NewMessageQueueDialog extends AbstractDialog {
             message = {AlphaWithDashRule.MESSAGE, BINDING_ID})
     private JTextField bindingId;
 
-    // TODO: New validation rule
     @FieldValidation(rule = RuleRegistry.NOT_EMPTY,
             message = {NotEmptyRule.MESSAGE, BINDING_TOPIC})
+    @FieldValidation(rule = RuleRegistry.ALPHA_WITH_PERIOD,
+            message = {AlphanumericWithUnderscoreRule.MESSAGE, BINDING_TOPIC})
     private JTextField bindingTopic;
 
+    private JTextField consumerDirectory;
+    private JTextField handlerDirectory;
+
     private JPanel contentPanel;
     private JButton buttonOK;
     private JButton buttonCancel;
+    private JLabel consumerDirectoryLabel;
+    private JLabel consumerClassLabel;
+    private JLabel maxMessagesLabel;
+    private JLabel bindingTopicLabel;//NOPMD
+    private JLabel handlerClassLabel;//NOPMD
+    private JLabel consumerNameLabel;//NOPMD
+    private JLabel handlerDirectoryLabel;//NOPMD
 
     private final Project project;
     private final String moduleName;
@@ -143,9 +160,13 @@ public NewMessageQueueDialog(final Project project, final PsiDirectory directory
 
         setContentPane(contentPanel);
         setModal(true);
-        setTitle(NewDataModelAction.ACTION_DESCRIPTION);
+        setTitle(NewMessageQueueAction.ACTION_DESCRIPTION);
         getRootPane().setDefaultButton(buttonOK);
 
+        for (final String connection : MessageQueueConnections.getList()) {
+            connectionName.addItem(connection);
+        }
+
         buttonOK.addActionListener((final ActionEvent event) -> onOK());
         buttonCancel.addActionListener((final ActionEvent event) -> onCancel());
 
@@ -164,6 +185,39 @@ public void windowClosing(final WindowEvent event) {
                 KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
                 JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
         );
+
+        this.topicName.getDocument().addDocumentListener(new DocumentAdapter() {
+            @Override
+            protected void textChanged(final @NotNull DocumentEvent event) {
+                updateIndefiersTextes();
+            }
+        });
+        this.handlerClass.getDocument().addDocumentListener(new DocumentAdapter() {
+            @Override
+            protected void textChanged(final @NotNull DocumentEvent event) {
+                updateBindingText();
+            }
+        });
+
+        connectionName.addActionListener(e -> toggleConsumer());
+    }
+
+    private void toggleConsumer() {
+        if (getConnectionName().equals(MessageQueueConnections.AMPQ.getType())) {
+            consumerDirectoryLabel.setVisible(false);
+            consumerDirectory.setVisible(false);
+            consumerClass.setVisible(false);
+            consumerClassLabel.setVisible(false);
+            maxMessages.setVisible(false);
+            maxMessagesLabel.setVisible(false);
+            return;
+        }
+        consumerDirectoryLabel.setVisible(true);
+        consumerDirectory.setVisible(true);
+        consumerClass.setVisible(true);
+        consumerClassLabel.setVisible(true);
+        maxMessages.setVisible(true);
+        maxMessagesLabel.setVisible(true);
     }
 
     /**
@@ -187,6 +241,10 @@ private void onOK() {
             generateConsumer();
             generateTopology();
             generatePublisher();
+            generateHandlerClass();
+            if (getConnectionName().equals(MessageQueueConnections.DB.getType())) {
+                generateConsumerClass();
+            }
             this.setVisible(false);
         }
     }
@@ -195,7 +253,7 @@ private void generateCommunication() {
         new QueueCommunicationGenerator(project, new QueueCommunicationData(
                 getTopicName(),
                 getHandlerName(),
-                getHandlerType(),
+                getHandlerClass(),
                 getHandlerMethod(),
                 getModuleName()
         )).generate(NewMessageQueueAction.ACTION_NAME, true);
@@ -205,11 +263,12 @@ private void generateConsumer() {
         new QueueConsumerGenerator(project, new QueueConsumerData(
                 getConsumerName(),
                 getQueueName(),
-                getConsumerType(),
+                getConsumerClass(),
                 getMaxMessages(),
                 getConnectionName(),
-                getModuleName()
-        )).generate(NewMessageQueueAction.ACTION_NAME, true);
+                getModuleName(),
+                getHandlerClass().concat("::").concat(getHandlerMethod())
+        )).generate(NewMessageQueueAction.ACTION_NAME, false);
     }
 
     private void generateTopology() {
@@ -220,7 +279,7 @@ private void generateTopology() {
                 getBindingTopic(),
                 getQueueName(),
                 getModuleName()
-        )).generate(NewMessageQueueAction.ACTION_NAME, true);
+        )).generate(NewMessageQueueAction.ACTION_NAME, false);
     }
 
     private void generatePublisher() {
@@ -229,7 +288,29 @@ private void generatePublisher() {
                 getConnectionName(),
                 getExchangeName(),
                 getModuleName()
-        )).generate(NewMessageQueueAction.ACTION_NAME, true);
+        )).generate(NewMessageQueueAction.ACTION_NAME, false);
+    }
+
+    private void generateHandlerClass() {
+        @NotNull final NamespaceBuilder handlerNamespaceBuilder = getHandlerNamespaceBuilder();
+        new MessageQueueClassGenerator(new MessageQueueClassData(
+            handlerClass.getText().trim(),
+            handlerNamespaceBuilder.getNamespace(),
+            handlerDirectory.getText().trim(),
+            handlerNamespaceBuilder.getClassFqn(),
+            MessageQueueClassPhp.Type.HANDLER
+        ), getModuleName(), project).generate(NewMessageQueueAction.ACTION_NAME, false);
+    }
+
+    private void generateConsumerClass() {
+        @NotNull final NamespaceBuilder consumerNamespaceBuilder = getConsumerNamespaceBuilder();
+        new MessageQueueClassGenerator(new MessageQueueClassData(
+            consumerClass.getText().trim(),
+            consumerNamespaceBuilder.getNamespace(),
+            consumerDirectory.getText().trim(),
+            consumerNamespaceBuilder.getClassFqn(),
+            MessageQueueClassPhp.Type.CONSUMER
+        ), getModuleName(), project).generate(NewMessageQueueAction.ACTION_NAME, false);
     }
 
     public String getTopicName() {
@@ -240,8 +321,30 @@ public String getHandlerName() {
         return handlerName.getText().trim();
     }
 
-    public String getHandlerType() {
-        return handlerType.getText().trim();
+    @NotNull
+    private NamespaceBuilder getHandlerNamespaceBuilder() {
+        return new NamespaceBuilder(
+            getModuleName(),
+            handlerClass.getText().trim(),
+            handlerDirectory.getText().trim()
+        );
+    }
+
+    @NotNull
+    private NamespaceBuilder getConsumerNamespaceBuilder() {
+        return new NamespaceBuilder(
+            getModuleName(),
+            consumerClass.getText().trim(),
+            consumerDirectory.getText().trim()
+        );
+    }
+
+    public String getHandlerClass() {
+        return getHandlerNamespaceBuilder().getClassFqn();
+    }
+
+    public String getConsumerClass() {
+        return getConsumerNamespaceBuilder().getClassFqn();
     }
 
     public String getHandlerMethod() {
@@ -256,16 +359,12 @@ public String getQueueName() {
         return queueName.getText().trim();
     }
 
-    public String getConsumerType() {
-        return consumerType.getText().trim();
-    }
-
     public String getMaxMessages() {
         return maxMessages.getText().trim();
     }
 
     public String getConnectionName() {
-        return connectionName.getText().trim();
+        return connectionName.getSelectedItem().toString();
     }
 
     public String getExchangeName() {
@@ -283,4 +382,24 @@ public String getBindingTopic() {
     public String getModuleName() {
         return moduleName;
     }
+
+    /**
+     * Update identifier texts.
+     */
+    public void updateIndefiersTextes() {
+        final String topicNameText = this.topicName.getText();
+        this.handlerName.setText(topicNameText.concat(".handler"));
+        this.consumerName.setText(topicNameText);
+        this.queueName.setText(topicNameText);
+        this.bindingTopic.setText(topicNameText);
+    }
+
+    /**
+     * Update identifier texts.
+     */
+    public void updateBindingText() {
+        final String handlerTypeText = this.handlerClass.getText();
+        this.consumerClass.setText(handlerTypeText.replace("Handler", "").concat("Consumer"));
+        this.bindingId.setText(handlerTypeText.replace("Handler", "").concat("Binding"));
+    }
 }
diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/MessageQueueClassGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/MessageQueueClassGenerator.java
new file mode 100644
index 000000000..02d5cf79f
--- /dev/null
+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/MessageQueueClassGenerator.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+package com.magento.idea.magento2plugin.actions.generation.generator;
+
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiDirectory;
+import com.intellij.psi.PsiFile;
+import com.jetbrains.php.lang.psi.PhpFile;
+import com.jetbrains.php.lang.psi.elements.PhpClass;
+import com.magento.idea.magento2plugin.actions.generation.data.MessageQueueClassData;
+import com.magento.idea.magento2plugin.actions.generation.generator.util.DirectoryGenerator;
+import com.magento.idea.magento2plugin.actions.generation.generator.util.FileFromTemplateGenerator;
+import com.magento.idea.magento2plugin.bundles.CommonBundle;
+import com.magento.idea.magento2plugin.bundles.ValidatorBundle;
+import com.magento.idea.magento2plugin.indexes.ModuleIndex;
+import com.magento.idea.magento2plugin.magento.files.MessageQueueClassPhp;
+import com.magento.idea.magento2plugin.magento.packages.File;
+import com.magento.idea.magento2plugin.util.GetFirstClassOfFile;
+import com.magento.idea.magento2plugin.util.GetPhpClassByFQN;
+import java.util.Properties;
+import javax.swing.JOptionPane;
+
+public class MessageQueueClassGenerator extends FileGenerator {
+    private final MessageQueueClassData messageQueueClassDataName;
+    private final Project project;
+    private final DirectoryGenerator directoryGenerator;
+    private final FileFromTemplateGenerator fileFromTemplateGenerator;
+    private final ValidatorBundle validatorBundle;
+    private final CommonBundle commonBundle;
+    private final String moduleName;
+    private final GetFirstClassOfFile getFirstClassOfFile;
+
+    /**
+     * Message queue handler constructor.
+     *
+     * @param messageQueueClassData MessageQueueHandlerData
+     * @param moduleName String
+     * @param project Project
+     */
+    public MessageQueueClassGenerator(
+            final MessageQueueClassData messageQueueClassData,
+            final String moduleName,
+            final Project project
+    ) {
+        super(project);
+
+        this.messageQueueClassDataName = messageQueueClassData;
+        this.directoryGenerator = DirectoryGenerator.getInstance();
+        this.fileFromTemplateGenerator = FileFromTemplateGenerator.getInstance(project);
+        this.validatorBundle = new ValidatorBundle();
+        this.commonBundle = new CommonBundle();
+        this.getFirstClassOfFile = GetFirstClassOfFile.getInstance();
+        this.project = project;
+        this.moduleName = moduleName;
+    }
+
+    @Override
+    public PsiFile generate(final String actionName) {
+        final PsiFile[] handlerFiles = new PsiFile[1];
+
+        WriteCommandAction.runWriteCommandAction(project, () -> {
+            PhpClass handler = GetPhpClassByFQN.getInstance(project).execute(
+                    messageQueueClassDataName.getFqn()
+            );
+
+            if (handler != null) {
+                final String errorMessage = this.validatorBundle.message(
+                        "validator.file.alreadyExists",
+                        "Handler Class"
+                );
+                JOptionPane.showMessageDialog(
+                        null,
+                        errorMessage,
+                        commonBundle.message("common.error"),
+                        JOptionPane.ERROR_MESSAGE
+                );
+
+                return;
+            }
+
+            handler = createHandlerClass(actionName);
+
+            if (handler == null) {
+                final String errorMessage = this.validatorBundle.message(
+                        "validator.file.cantBeCreated",
+                        "Handler Class"
+                );
+                JOptionPane.showMessageDialog(
+                        null,
+                        errorMessage,
+                        commonBundle.message("common.error"),
+                        JOptionPane.ERROR_MESSAGE
+                );
+
+                return;
+            }
+
+            handlerFiles[0] = handler.getContainingFile();
+        });
+
+        return handlerFiles[0];
+    }
+
+    @Override
+    protected void fillAttributes(final Properties attributes) {
+        attributes.setProperty("NAMESPACE", messageQueueClassDataName.getNamespace());
+        attributes.setProperty("CLASS_NAME", messageQueueClassDataName.getName());
+    }
+
+    private PhpClass createHandlerClass(final String actionName) {
+        PsiDirectory parentDirectory = ModuleIndex.getInstance(project)
+                .getModuleDirectoryByModuleName(this.moduleName);
+        final PsiFile handlerFile;
+        final String[] handlerDirectories = messageQueueClassDataName.getPath().split(
+                File.separator
+        );
+        for (final String handlerDirectory: handlerDirectories) {
+            parentDirectory = directoryGenerator.findOrCreateSubdirectory(
+                    parentDirectory, handlerDirectory
+            );
+        }
+
+        final Properties attributes = getAttributes();
+
+        handlerFile = fileFromTemplateGenerator.generate(
+                new MessageQueueClassPhp(
+                        messageQueueClassDataName.getName(),
+                        messageQueueClassDataName.getType()
+                ),
+                attributes,
+                parentDirectory,
+                actionName
+        );
+
+        if (handlerFile == null) {
+            return null;
+        }
+
+        return getFirstClassOfFile.execute((PhpFile) handlerFile);
+    }
+}
diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/QueueConsumerGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/QueueConsumerGenerator.java
index 961b55bfa..5e1ada751 100644
--- a/src/com/magento/idea/magento2plugin/actions/generation/generator/QueueConsumerGenerator.java
+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/QueueConsumerGenerator.java
@@ -14,6 +14,7 @@
 import com.intellij.psi.xml.XmlTag;
 import com.magento.idea.magento2plugin.actions.generation.data.QueueConsumerData;
 import com.magento.idea.magento2plugin.actions.generation.generator.util.FindOrCreateQueueConsumerXml;
+import com.magento.idea.magento2plugin.magento.packages.MessageQueueConnections;
 import java.util.Properties;
 
 public class QueueConsumerGenerator extends FileGenerator {
@@ -58,9 +59,14 @@ public PsiFile generate(final String actionName) {
                 final XmlTag consumerTag = rootTag.createChildTag("consumer", null, null, false);
                 consumerTag.setAttribute("name", consumerData.getConsumerName());
                 consumerTag.setAttribute("queue", consumerData.getQueueName());
-                consumerTag.setAttribute("consumerInstance", consumerData.getConsumerType());
                 consumerTag.setAttribute("connection", consumerData.getConnectionName());
-                consumerTag.setAttribute("maxMessages", consumerData.getMaxMessages());
+
+                if (consumerData.getConnectionName().equals(MessageQueueConnections.DB.getType())) {
+                    consumerTag.setAttribute("consumerInstance", consumerData.getConsumerClass());
+                    consumerTag.setAttribute("maxMessages", consumerData.getMaxMessages());
+                } else {
+                    consumerTag.setAttribute("handler", consumerData.getHandler());
+                }
 
                 rootTag.addSubTag(consumerTag, false);
             }
diff --git a/src/com/magento/idea/magento2plugin/inspections/xml/PluginDeclarationInspection.java b/src/com/magento/idea/magento2plugin/inspections/xml/PluginDeclarationInspection.java
index 6fe323cdc..99412796d 100644
--- a/src/com/magento/idea/magento2plugin/inspections/xml/PluginDeclarationInspection.java
+++ b/src/com/magento/idea/magento2plugin/inspections/xml/PluginDeclarationInspection.java
@@ -71,6 +71,9 @@ public void visitFile(final PsiFile file) {
 
                     final XmlAttribute pluginNameAttribute =
                             pluginXmlTag.getAttribute(ModuleDiXml.NAME_ATTR);
+                    if (pluginNameAttribute == null) {
+                        continue;
+                    }
 
                     final String pluginNameAttributeValue = pluginNameAttribute.getValue();
                     if (pluginNameAttributeValue == null) {
diff --git a/src/com/magento/idea/magento2plugin/magento/files/MessageQueueClassPhp.java b/src/com/magento/idea/magento2plugin/magento/files/MessageQueueClassPhp.java
new file mode 100644
index 000000000..5815ad8dc
--- /dev/null
+++ b/src/com/magento/idea/magento2plugin/magento/files/MessageQueueClassPhp.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+package com.magento.idea.magento2plugin.magento.files;
+
+import com.intellij.lang.Language;
+import com.jetbrains.php.lang.PhpLanguage;
+
+public class MessageQueueClassPhp implements ModuleFileInterface {
+    public static final String HANDLER_TEMPLATE = "Magento Message Queue Handler Class";
+    public static final String CONSUMER_TEMPLATE = "Magento Message Queue Consumer Class";
+    public static final String FILE_EXTENSION = "php";
+    private String className;
+    private final Type type;
+
+    /**
+     * Constructor.
+     *
+     * @param className String
+     * @param type Type
+     */
+    public MessageQueueClassPhp(
+            final String className,
+            final Type type
+    ) {
+        this.className = className;
+        this.type = type;
+    }
+
+    /**
+     * Set class name.
+     *
+     * @param className String
+     */
+    public void setClassName(final String className) {
+        this.className = className;
+    }
+
+    @Override
+    public String getFileName() {
+        return String.format("%s.%s", className, FILE_EXTENSION);
+    }
+
+    @Override
+    public String getTemplate() {
+        if (type.equals(Type.CONSUMER)) {
+            return CONSUMER_TEMPLATE;
+        }
+        return HANDLER_TEMPLATE;
+    }
+
+    @Override
+    public Language getLanguage() {
+        return PhpLanguage.INSTANCE;
+    }
+
+    public enum Type {
+        HANDLER,
+        CONSUMER
+    }
+}
diff --git a/src/com/magento/idea/magento2plugin/magento/packages/MessageQueueConnections.java b/src/com/magento/idea/magento2plugin/magento/packages/MessageQueueConnections.java
new file mode 100644
index 000000000..e3683914b
--- /dev/null
+++ b/src/com/magento/idea/magento2plugin/magento/packages/MessageQueueConnections.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+package com.magento.idea.magento2plugin.magento.packages;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public enum MessageQueueConnections {
+    DB("db"),
+    AMPQ("ampq");
+
+    private final String type;
+
+    /**
+     * Queue connection constructor.
+     *
+     * @param type String
+     */
+    MessageQueueConnections(final String type) {
+        this.type = type;
+    }
+
+    /**
+     * Get connection type.
+     *
+     * @return String
+     */
+    public String getType() {
+        return type;
+    }
+
+    /**
+     * Get connection type by name.
+     *
+     * @param typeName type name
+     * @return Request Interface
+     */
+    public static String getConnectionTypeByName(final String typeName) {
+        return MessageQueueConnections.valueOf(typeName).getType();
+    }
+
+    /**
+     * Get list of connection types.
+     *
+     * @return List connection types.
+     */
+    public static List getList() {
+        final List typeList = new ArrayList<>();
+
+        for (final MessageQueueConnections type: MessageQueueConnections.values()) {
+            typeList.add(getConnectionTypeByName(type.name()));
+        }
+
+        return typeList;
+    }
+}
diff --git a/src/com/magento/idea/magento2plugin/util/magento/MagentoVersionUtil.java b/src/com/magento/idea/magento2plugin/util/magento/MagentoVersionUtil.java
index 230d22b21..7b5c22180 100644
--- a/src/com/magento/idea/magento2plugin/util/magento/MagentoVersionUtil.java
+++ b/src/com/magento/idea/magento2plugin/util/magento/MagentoVersionUtil.java
@@ -87,6 +87,10 @@ public static boolean compare(final String version1, final String version2) {
             return true;
         }
 
+        if (version1.isEmpty()) {
+            return false;
+        }
+
         final String[] version1s = version1.split("\\.");
         final String[] version2s = version2.split("\\.");
         for (int i = 0; i < 2; i++) {
diff --git a/testData/actions/generation/generator/DataModelGenerator/generateDataModel/Sample.php b/testData/actions/generation/generator/DataModelGenerator/generateDataModel/Sample.php
index 50cf49550..f09ef5e6b 100644
--- a/testData/actions/generation/generator/DataModelGenerator/generateDataModel/Sample.php
+++ b/testData/actions/generation/generator/DataModelGenerator/generateDataModel/Sample.php
@@ -1,5 +1,4 @@
 
+
+    
+
diff --git a/testData/actions/generation/generator/QueueConsumerGenerator/generateConsumerXmlFile/queue_consumer.xml b/testData/actions/generation/generator/QueueConsumerGenerator/generateConsumerDbXmlFile/queue_consumer.xml
similarity index 66%
rename from testData/actions/generation/generator/QueueConsumerGenerator/generateConsumerXmlFile/queue_consumer.xml
rename to testData/actions/generation/generator/QueueConsumerGenerator/generateConsumerDbXmlFile/queue_consumer.xml
index ca08e43aa..f7f122ad5 100644
--- a/testData/actions/generation/generator/QueueConsumerGenerator/generateConsumerXmlFile/queue_consumer.xml
+++ b/testData/actions/generation/generator/QueueConsumerGenerator/generateConsumerDbXmlFile/queue_consumer.xml
@@ -1,6 +1,6 @@
 
 
-    
 
diff --git a/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsBatchResolverInterface.php b/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsBatchResolverInterface.php
index 0b099ae30..a5f0a14c8 100644
--- a/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsBatchResolverInterface.php
+++ b/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsBatchResolverInterface.php
@@ -3,7 +3,6 @@
  * Copyright © Magento, Inc. All rights reserved.
  * See COPYING.txt for license details.
  */
-declare(strict_types=1);
 
 namespace Magento\CatalogGraphQl\Model\Resolver;
 
diff --git a/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsBatchServiceContractResolverInterface.php b/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsBatchServiceContractResolverInterface.php
index 88de2502f..37f8002e3 100644
--- a/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsBatchServiceContractResolverInterface.php
+++ b/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsBatchServiceContractResolverInterface.php
@@ -3,7 +3,6 @@
  * Copyright © Magento, Inc. All rights reserved.
  * See COPYING.txt for license details.
  */
-declare(strict_types=1);
 
 namespace Magento\CatalogGraphQl\Model\Resolver;
 
diff --git a/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsResolverInterface.php b/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsResolverInterface.php
index 5a60d1009..1f2c0c018 100644
--- a/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsResolverInterface.php
+++ b/testData/project/magento2/vendor/magento/module-catalog-graph-ql/Model/Resolver/ImplementsResolverInterface.php
@@ -3,7 +3,6 @@
  * Copyright © Magento, Inc. All rights reserved.
  * See COPYING.txt for license details.
  */
-declare(strict_types=1);
 
 namespace Magento\CatalogGraphQl\Model\Resolver;
 
diff --git a/tests/com/magento/idea/magento2plugin/actions/generation/generator/MessageQueueClassGeneratorTest.java b/tests/com/magento/idea/magento2plugin/actions/generation/generator/MessageQueueClassGeneratorTest.java
new file mode 100644
index 000000000..84cfc1d77
--- /dev/null
+++ b/tests/com/magento/idea/magento2plugin/actions/generation/generator/MessageQueueClassGeneratorTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+package com.magento.idea.magento2plugin.actions.generation.generator;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFile;
+import com.magento.idea.magento2plugin.actions.generation.data.MessageQueueClassData;
+import com.magento.idea.magento2plugin.magento.files.MessageQueueClassPhp;
+
+public class MessageQueueClassGeneratorTest extends BaseGeneratorTestCase {
+    private static final String MODULE_NAME = "Foo_Bar";
+
+    private static final String HANDLER_EXPECTED_DIRECTORY = "src/app/code/Foo/Bar/Queue/Handler";
+    private static final String HANDLER_CLASS_NAME = "MyHandler";
+    private static final String HANDLER_NAMESPACE = "Foo\\Bar\\Queue\\Handler";
+    private static final String HANDLER_PATH = "Queue/Handler";
+    private static final String HANDLER_FQN = "\\Foo\\Bar\\Queue\\Handler\\MyHandler";
+
+    private static final String CONSUMER_EXPECTED_DIRECTORY = "src/app/code/Foo/Bar/Queue/Consumer";
+    private static final String CONSUMER_CLASS_NAME = "MyConsumer";
+    private static final String CONSUMER_NAMESPACE = "Foo\\Bar\\Queue\\Consumer";
+    private static final String CONSUMER_PATH = "Queue/Consumer";
+    private static final String CONSUMER_FQN = "\\Foo\\Bar\\Queue\\Handler\\MyConsumer";
+
+    /**
+     * Test handler class file generation.
+     */
+    public void testGenerateHandler() {
+        final Project project = myFixture.getProject();
+        final MessageQueueClassData messageQueueClassData = new MessageQueueClassData(
+                HANDLER_CLASS_NAME,
+                HANDLER_NAMESPACE,
+                HANDLER_PATH,
+                HANDLER_FQN,
+                MessageQueueClassPhp.Type.HANDLER
+        );
+        final MessageQueueClassGenerator generator;
+        generator = new MessageQueueClassGenerator(
+            messageQueueClassData,
+            MODULE_NAME,
+            project
+        );
+
+        final PsiFile messageQueue = generator.generate("test");
+        final String filePath = this.getFixturePath("MyHandler.php");
+        final PsiFile expectedFile = myFixture.configureByFile(filePath);
+
+        assertGeneratedFileIsCorrect(
+                expectedFile,
+                HANDLER_EXPECTED_DIRECTORY,
+                messageQueue
+        );
+    }
+
+    /**
+     * Test consumer class file generation.
+     */
+    public void testGenerateConsumer() {
+        final Project project = myFixture.getProject();
+        final MessageQueueClassData messageQueueClassData = new MessageQueueClassData(
+                CONSUMER_CLASS_NAME,
+                CONSUMER_NAMESPACE,
+                CONSUMER_PATH,
+                CONSUMER_FQN,
+                MessageQueueClassPhp.Type.CONSUMER
+        );
+        final MessageQueueClassGenerator generator;
+        generator = new MessageQueueClassGenerator(
+            messageQueueClassData,
+            MODULE_NAME,
+            project
+        );
+
+        final PsiFile messageQueue = generator.generate("test");
+        final String filePath = this.getFixturePath("MyConsumer.php");
+        final PsiFile expectedFile = myFixture.configureByFile(filePath);
+
+        assertGeneratedFileIsCorrect(
+                expectedFile,
+                CONSUMER_EXPECTED_DIRECTORY,
+                messageQueue
+        );
+    }
+}
diff --git a/tests/com/magento/idea/magento2plugin/actions/generation/generator/QueueConsumerGeneratorTest.java b/tests/com/magento/idea/magento2plugin/actions/generation/generator/QueueConsumerGeneratorTest.java
index 65613f482..7b2813ed2 100644
--- a/tests/com/magento/idea/magento2plugin/actions/generation/generator/QueueConsumerGeneratorTest.java
+++ b/tests/com/magento/idea/magento2plugin/actions/generation/generator/QueueConsumerGeneratorTest.java
@@ -16,14 +16,16 @@ public class QueueConsumerGeneratorTest extends BaseGeneratorTestCase {
     private static final String QUEUE_NAME = "queue.name";
     private static final String CONSUMER_TYPE = "Foo\\Bar\\Model\\Consumer";
     private static final String MAX_MESSAGES = "100";
-    private static final String CONNECTION_NAME = "amqp";
+    private static final String CONNECTION_AMPQ = "amqp";
+    private static final String CONNECTION_DB = "db";
     private static final String MODULE_NAME = "Foo_Bar";
     private static final String EXPECTED_DIRECTORY = "src/app/code/Foo/Bar/etc";
+    private static final String HANDLER = "Foo/Bar/Handler.php::execute";
 
     /**
-     * Tests for generation of queue_consumer.xml file.
+     * Tests for generation of queue_consumer.xml file for the DB connection type.
      */
-    public void testGenerateConsumerXmlFile() {
+    public void testGenerateConsumerDbXmlFile() {
         final String filePath = this.getFixturePath(QueueConsumerXml.fileName);
         final PsiFile expectedFile = myFixture.configureByFile(filePath);
         final Project project = myFixture.getProject();
@@ -34,8 +36,34 @@ public void testGenerateConsumerXmlFile() {
                         QUEUE_NAME,
                         CONSUMER_TYPE,
                         MAX_MESSAGES,
-                        CONNECTION_NAME,
-                        MODULE_NAME
+                        CONNECTION_DB,
+                        MODULE_NAME,
+                        HANDLER
+                )
+        );
+
+        final PsiFile file = consumerGenerator.generate(NewMessageQueueAction.ACTION_NAME);
+
+        assertGeneratedFileIsCorrect(expectedFile, EXPECTED_DIRECTORY, file);
+    }
+
+    /**
+     * Tests for generation of queue_consumer.xml file for the AMPQ connection type.
+     */
+    public void testGenerateConsumerAmpqXmlFile() {
+        final String filePath = this.getFixturePath(QueueConsumerXml.fileName);
+        final PsiFile expectedFile = myFixture.configureByFile(filePath);
+        final Project project = myFixture.getProject();
+        final QueueConsumerGenerator consumerGenerator = new QueueConsumerGenerator(
+                project,
+                new QueueConsumerData(
+                    CONSUMER_NAME,
+                    QUEUE_NAME,
+                    CONSUMER_TYPE,
+                    MAX_MESSAGES,
+                    CONNECTION_AMPQ,
+                    MODULE_NAME,
+                    HANDLER
                 )
         );