7 Replies Latest reply on Apr 25, 2017 5:31 AM by vsharma-2 RSS
    vsharma-2 Newbie

    Unable to Invoke Service : No service handler defined for service on thing [Test]

    I have created one extension and i m trying to test the service and getting below error.

    Please suggest possible ways for it.

     

     

    [context: com.thingworx.webservices.context.HttpExecutionContext@44302b5c][message: Unable to Invoke Service SendMessageWithImage on Test : No service handler defined for service SendMessageWithImage on thing [Test]]

     

    Unable to create service handler for SendMessageWithImage in MailThingPackage:ThingPackage : Unable to bind service [SendMessageWithImage] to method on class [com.test.tnt.ext.mail.MailThing]

      • Re: Unable to Invoke Service : No service handler defined for service on thing [Test]
        supandey Collaborator

        Vaibhav, have you verified if your Mail Thing is working as expected i.e. are you able to send/receive emails with that? Have you tried testing the SendMessageWithImage?

        • Re: Unable to Invoke Service : No service handler defined for service on thing [Test]
          Ankit Gupta Ninja

          Vaibhav Sharma,

           

          Is this extension a custom extension or are you using the mail extension downloaded from the ThingWorx marketplace?

              • Re: Unable to Invoke Service : No service handler defined for service on thing [Test]
                Ankit Gupta Ninja

                Vaibhav Sharma,

                 

                Please share the definition/code for SendMessageWithImage service.

                  • Re: Unable to Invoke Service : No service handler defined for service on thing [Test]
                    vsharma-2 Newbie
                    package com.test.tnt.ext.mail;
                    
                    
                    import com.thingworx.common.RESTAPIConstants;
                    import com.thingworx.common.exceptions.InvalidRequestException;
                    import com.thingworx.entities.utils.ThingUtilities;
                    import com.thingworx.logging.LogUtilities;
                    import com.thingworx.metadata.annotations.ThingworxConfigurationTableDefinitions;
                    import com.thingworx.metadata.annotations.ThingworxServiceDefinition;
                    import com.thingworx.metadata.annotations.ThingworxServiceParameter;
                    import com.thingworx.things.Thing;
                    import com.thingworx.things.repository.FileRepositoryThing;
                    import java.io.PrintStream;
                    import java.util.Properties;
                    import javax.activation.DataHandler;
                    import javax.mail.Authenticator;
                    import javax.mail.Message;
                    import javax.mail.Multipart;
                    import javax.mail.PasswordAuthentication;
                    import javax.mail.Session;
                    import javax.mail.Transport;
                    import javax.mail.internet.InternetAddress;
                    import javax.mail.internet.MimeBodyPart;
                    import javax.mail.internet.MimeMessage;
                    import javax.mail.internet.MimeMultipart;
                    import javax.mail.util.ByteArrayDataSource;
                    import org.apache.commons.exec.LogOutputStream;
                    import org.apache.commons.lang3.StringUtils;
                    import org.slf4j.Logger;
                    
                    
                    @ThingworxConfigurationTableDefinitions(tables={@com.thingworx.metadata.annotations.ThingworxConfigurationTableDefinition(name="ConnectionInfo", description="Mail Server Connection Parameters", isMultiRow=false, ordinal=0, dataShape=@com.thingworx.metadata.annotations.ThingworxDataShapeDefinition(fields={@com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=0, name="smtpServer", description="SMTP server name", baseType="STRING", aspects={"defaultValue:smtp.domain.com", "friendlyName:SMTP Server"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=1, name="smtpPort", description="SMTP server port", baseType="NUMBER", aspects={"defaultValue:80", "friendlyName:SMTP Server Port"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=2, name="pop3Server", description="POP3 server name", baseType="STRING", aspects={"defaultValue:pop3.domain.com", "friendlyName:POP3 Server"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=3, name="pop3Port", description="POP3 server port", baseType="NUMBER", aspects={"defaultValue:110", "friendlyName:POP3 Server Port"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=4, name="useTLS", description="Use transport layer security", baseType="BOOLEAN", aspects={"defaultValue:false", "friendlyName:Use TLS"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=5, name="useSSL", description="Use an SSL connection", baseType="BOOLEAN", aspects={"defaultValue:false", "friendlyName:Use SSL"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=6, name="accountId", description="Mail account user id", baseType="STRING", aspects={"defaultValue:account@domain.com", "friendlyName:Mail Account User"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=7, name="accountPassword", description="Mail account password", baseType="PASSWORD", aspects={"friendlyName:Mail Account Password"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=8, name="defaultFrom", description="Default From field", baseType="STRING", aspects={"friendlyName:Default From Field"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=9, name="connectionTimeout", description="Timeout (milliseconds) to establish a connection", baseType="NUMBER", aspects={"defaultValue:30000", "friendlyName:Connection Timeout"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=10, name="operationTimeout", description="Timeout (milliseconds) to perform an operation", baseType="NUMBER", aspects={"defaultValue:30000", "friendlyName:Operation Timeout"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=11, name="socksHost", description="Specifies the host name of a SOCKS5 proxy server that will be used for connections to the mail server", baseType="STRING", aspects={"defaultValue:", "friendlyName:Socks Host"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=12, name="socksPort", description="Specifies the port number for the SOCKS5 proxy server", baseType="NUMBER", aspects={"defaultValue:1080", "friendlyName:Socks Port"}), @com.thingworx.metadata.annotations.ThingworxFieldDefinition(ordinal=13, name="fileRepository", description="File Repository for recieved attachments", baseType="THINGNAME", aspects={"defaultValue:SystemRepository", "friendlyName:Attachment File Repository"})}))})
                    public class MailThing extends Thing{
                      private static Logger _logger = LogUtilities.getInstance().getApplicationLogger(MailThing.class);
                      private String _smtpServer = "";
                      private Number _smtpPort = Integer.valueOf(80);
                      private String _accountId = "";
                      private String _accountPassword = "";
                      private String _defaultFrom = "";
                      private Number _connectionTimeout = Integer.valueOf(30000);
                      private Number _operationTimeout = Integer.valueOf(30000);
                      private String _socksServer = "";
                      private Number _socksPort = Integer.valueOf(1080);
                      private Boolean _useSSL = Boolean.valueOf(false);
                      private Boolean _useTLS = Boolean.valueOf(false);
                      private Boolean _debug = Boolean.valueOf(false);
                    
                      protected void initializeThing(){
                        this._smtpServer = ((String)getConfigurationSetting("ConnectionInfo", "smtpServer"));
                        this._smtpPort = ((Number)getConfigurationSetting("ConnectionInfo", "smtpPort"));
                        this._accountId = ((String)getConfigurationSetting("ConnectionInfo", "accountId"));
                        this._accountPassword = ((String)getConfigurationSetting("ConnectionInfo", "accountPassword"));
                        this._defaultFrom = ((String)getConfigurationSetting("ConnectionInfo", "defaultFrom"));
                        this._connectionTimeout = ((Number)getConfigurationSetting("ConnectionInfo", "connectionTimeout"));
                        this._operationTimeout = ((Number)getConfigurationSetting("ConnectionInfo", "operationTimeout"));
                        this._useSSL = ((Boolean)getConfigurationSetting("ConnectionInfo", "useSSL"));
                        this._useTLS = ((Boolean)getConfigurationSetting("ConnectionInfo", "useTLS"));
                        this._socksServer = ((String)getConfigurationSetting("ConnectionInfo", "socksHost"));
                        this._socksPort = ((Number)getConfigurationSetting("ConnectionInfo", "socksPort"));
                      }
                    /* 
                      @ThingworxServiceDefinition(name="IsDebug", description="State of Email Debugger")
                      @ThingworxServiceResult(name="result", description="State of Email Debugger", baseType="BOOLEAN")
                      public boolean IsDebug(){
                        return this._debug.booleanValue();
                      }
                    
                      @ThingworxServiceDefinition(name="SetDebug", description="Set debug mode on or off")
                      public void SetDebug(@ThingworxServiceParameter(name="debug", description="Set debug mode on or off", baseType="BOOLEAN", aspects={"defaultValue:false"}) Boolean debug){
                        this._debug = debug;
                      }
                      */
                    
                      @ThingworxServiceDefinition(name="SendMessageWithAttachment", description="Send a simple textual e-mail message with a file attachment")
                      public void SendMessageWithAttachment(@ThingworxServiceParameter(name="from", description="", baseType="STRING") String from, @ThingworxServiceParameter(name="to", description="", baseType="STRING") String to, @ThingworxServiceParameter(name="cc", description="", baseType="STRING") String cc, @ThingworxServiceParameter(name="bcc", description="", baseType="STRING") String bcc, @ThingworxServiceParameter(name="subject", description="", baseType="STRING") String subject, @ThingworxServiceParameter(name="body", description="", baseType="HTML") String body, @ThingworxServiceParameter(name="fileRepository", description="File repository", baseType="THINGNAME") String fileRepository, @ThingworxServiceParameter(name="path", description="Path to file", baseType="STRING") String path, @ThingworxServiceParameter(name="attachmentName", description="File name for attachment", baseType="STRING") String attachmentName, @ThingworxServiceParameter(name="mimeType", description="Mime type for attachment", baseType="STRING") String mimeType) throws Exception{
                       
                       _logger.debug("Enter into SendMessageWithAttachment() Method");
                       _logger.info("Enter into SendMessageWithAttachment() Method");
                      
                      if(StringUtils.isBlank(fileRepository)){
                          throw new InvalidRequestException("File Repository Name Must Be Provided", RESTAPIConstants.StatusCode.STATUS_BAD_REQUEST);
                        }
                       
                      if(StringUtils.isBlank(path)){
                          throw new InvalidRequestException("File Path Must Be Provided", RESTAPIConstants.StatusCode.STATUS_BAD_REQUEST);
                        }
                        Thing thing = ThingUtilities.findThing(fileRepository);
                       
                        _logger.debug("Creating Thing for fileRepository");
                        _logger.info("Creating Thing for fileRepository");
                       
                        if(StringUtils.isBlank(""+thing)){
                          throw new InvalidRequestException("File Repository [" + fileRepository + "] Does Not Exist", RESTAPIConstants.StatusCode.STATUS_NOT_FOUND);
                        }
                        if(!(thing instanceof FileRepositoryThing)){
                          throw new InvalidRequestException("Thing [" + fileRepository + "] Is Not A File Repository", RESTAPIConstants.StatusCode.STATUS_BAD_REQUEST);
                        }
                        FileRepositoryThing fileRepoThing = (FileRepositoryThing)thing;
                        byte[] data = fileRepoThing.LoadBinary(path);
                       
                        _logger.debug("After converting path into byte stream");
                        _logger.info("After converting path into byte stream");
                       
                        SendMessage(from, to, cc, bcc, subject, body, data, attachmentName, mimeType);
                       
                        _logger.debug("Exit From SendMessageWithAttachment() Method");
                        _logger.info("Exit From SendMessageWithAttachment() Method");
                      }
                    
                      @ThingworxServiceDefinition(name="SendMessageWithImage", description="Send a simple textual e-mail message with an image attachment")
                      public void SendMessage(@ThingworxServiceParameter(name="from", description="", baseType="STRING") String from, @ThingworxServiceParameter(name="to", description="", baseType="STRING") String to, @ThingworxServiceParameter(name="cc", description="", baseType="STRING") String cc, @ThingworxServiceParameter(name="bcc", description="", baseType="STRING") String bcc, @ThingworxServiceParameter(name="subject", description="", baseType="STRING") String subject, @ThingworxServiceParameter(name="body", description="", baseType="HTML") String body, @ThingworxServiceParameter(name="image", description="Image content", baseType="IMAGE") byte[] image, @ThingworxServiceParameter(name="attachmentName", description="File name for attachment", baseType="STRING") String attachmentName, @ThingworxServiceParameter(name="mimeType", description="Mime type for attachment", baseType="STRING") String mimeType) throws Exception{
                    
                    
                       _logger.debug("Enter into sendMessage() Method");
                       _logger.info("Enter into sendMessage() Method");
                      
                      if((StringUtils.isBlank(mimeType)) && (StringUtils.isNotBlank(""+image))){
                          throw new InvalidRequestException("Mime type Must Be Provided", RESTAPIConstants.StatusCode.STATUS_BAD_REQUEST);
                        }
                       
                      if((StringUtils.isBlank(attachmentName)) && (StringUtils.isNotBlank(""+image))){
                          throw new InvalidRequestException("Attachment Name Must Be Provided", RESTAPIConstants.StatusCode.STATUS_BAD_REQUEST);
                        }
                       
                      try{
                      _logger.debug("Before setting properties of server");
                      _logger.info("Before setting properties of server");
                    
                          Properties props = new Properties();
                          props.setProperty("mail.transport.protocol", "smtp");
                          props.setProperty("mail.host", this._smtpServer);
                          if(this._useTLS.booleanValue()){
                        
                         _logger.debug("Enabling TLS Value");
                         _logger.info("Enabling TLS Value");
                            props.put("mail.smtp.starttls.enable", "true");
                          }
                          if(this._useSSL.booleanValue()){
                        
                         _logger.info("Enabling SSL Value");
                         _logger.debug("Enabling SSL Value");
                        
                            props.put("mail.smtp.socketFactory.port", new Integer(this._smtpPort.intValue()).toString());
                            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
                            props.put("mail.smtp.socketFactory.fallback", "false");
                            props.setProperty("mail.smtp.quitwait", "false");
                          }
                          props.setProperty("mail.smtp.port", new Integer(this._smtpPort.intValue()).toString());
                          props.put("mail.debug", this._debug);
                          Integer connTimeout = Integer.valueOf(this._connectionTimeout.intValue());
                          props.setProperty("mail.smtp.connectiontimeout", connTimeout.toString());
                          Integer opTimeout = Integer.valueOf(this._operationTimeout.intValue());
                          props.setProperty("mail.smtp.timeout", opTimeout.toString());
                         
                          _logger.debug("Setting Timeout Values");
                          _logger.info("Setting Timeout Values");
                          this._socksServer = this._socksServer.trim();
                         
                          if (StringUtils.isNotBlank(this._socksServer)){
                            props.setProperty("mail.smtp.socks.host", this._socksServer);
                            Integer thesocksport = Integer.valueOf(this._socksPort.intValue());
                            props.setProperty("mail.smtp.socks.port", thesocksport.toString());
                            _logger.debug("Setting Socket Server IP or Port");
                            _logger.info("Setting Socket Server IP or Port");
                          }
                          this._accountId = this._accountId.trim();
                          Session mailSession;
                         
                          if (StringUtils.isNotBlank(this._accountId)){
                            props.setProperty("mail.smtp.auth", Boolean.toString(true));
                            final String uid = this._accountId;
                            final String pwd = this._accountPassword;
                           
                            _logger.debug("Setting AccountId and Password");
                            _logger.info("Setting AccountId and Password");
                           
                            Authenticator auth = new Authenticator(){
                              protected PasswordAuthentication getPasswordAuthentication(){
                             _logger.debug("Inside Password Authentication");
                             _logger.info("Inside Password Authentication");
                                return new PasswordAuthentication(uid, pwd);
                              }
                            };
                            mailSession = Session.getInstance(props, auth);
                          }else{
                            props.put("mail.smtp.auth", Boolean.toString(false));
                            mailSession = Session.getInstance(props);
                          }
                          mailSession.setDebug(this._debug.booleanValue());
                         
                          if (mailSession.getDebug()){
                            _logger.debug("SendMail debug mode is ON");
                            _logger.info("SendMail debug mode is ON");
                            LogOutputStream sendMailDebugOut = new LogOutputStream(){
                              protected void processLine(String line, int level){
                                MailThing._logger.debug(line);
                              }
                            };
                            mailSession.setDebugOut(new PrintStream(sendMailDebugOut));
                          }
                          MimeMessage message = new MimeMessage(mailSession);
                          message.setSubject(subject, "UTF-8");
                          String fromAddress = from;
                         
                          if (StringUtils.isBlank(fromAddress)){
                            fromAddress = this._defaultFrom;
                           
                            if(StringUtils.isBlank(fromAddress)){
                              throw new InvalidRequestException("No sender address specified.", RESTAPIConstants.StatusCode.STATUS_BAD_REQUEST);
                            }
                          }
                          message.setFrom(new InternetAddress(fromAddress));
                          message.setSender(new InternetAddress(fromAddress));
                          if(body == null){
                            body = "";
                          }
                         
                          if(StringUtils.isNotBlank(""+image)){
                            Multipart multipart = new MimeMultipart();
                            MimeBodyPart messageBodyPart = new MimeBodyPart();
                            messageBodyPart.setContent(body, "text/html; charset=utf-8");
                            multipart.addBodyPart(messageBodyPart);
                            MimeBodyPart attachmentBodyPart = new MimeBodyPart();
                            ByteArrayDataSource source = new ByteArrayDataSource(image, mimeType);
                            attachmentBodyPart.setDataHandler(new DataHandler(source));
                            attachmentBodyPart.setFileName(attachmentName);
                            multipart.addBodyPart(attachmentBodyPart);
                            message.setContent(multipart);
                          }else{
                            message.setContent(body, "text/html; charset=utf-8");
                          }
                         
                          if((StringUtils.isBlank(to)) && (StringUtils.isBlank(cc)) && (StringUtils.isBlank(bcc))) {
                            throw new InvalidRequestException("No recipient address specified.", RESTAPIConstants.StatusCode.STATUS_BAD_REQUEST);
                          }
                         
                          if (StringUtils.isNotBlank(to)){
                            String[] addresses = to.split(";");
                            InternetAddress[] recipients = new InternetAddress[addresses.length];
                           
                            for(int i = 0; i < addresses.length; i++){
                              recipients[i] = new InternetAddress(addresses[i].trim());
                            }
                            message.setRecipients(Message.RecipientType.TO, recipients);
                          }
                         
                          if(StringUtils.isNotBlank(cc)){
                            String[] addresses = cc.split(";");
                            InternetAddress[] recipients = new InternetAddress[addresses.length];
                            for(int i = 0; i < addresses.length; i++){
                              recipients[i] = new InternetAddress(addresses[i].trim());
                            }
                            message.setRecipients(Message.RecipientType.CC, recipients);
                          }
                         
                          if(StringUtils.isNotBlank(bcc)){
                            String[] addresses = bcc.split(";");
                            InternetAddress[] recipients = new InternetAddress[addresses.length];
                            for(int i = 0; i < addresses.length; i++){
                              recipients[i] = new InternetAddress(addresses[i].trim());
                            }
                            message.setRecipients(Message.RecipientType.BCC, recipients);
                          }
                          Transport.send(message, message.getAllRecipients());
                        }catch (Exception e){
                          _logger.error("Unable to Send Message: {}", e.getMessage(), e);
                          throw e;
                        }
                      }
                    
                      protected static class ConfigConstants{
                        public static final String ConnectionInfo = "ConnectionInfo";
                        public static final String SmtpServer = "smtpServer";
                        public static final String SmtpPort = "smtpPort";
                        public static final String UseSSL = "useSSL";
                        public static final String UseTLS = "useTLS";
                        public static final String AccountId = "accountId";
                        public static final String AccountPassword = "accountPassword";
                        public static final String DefaultFrom = "defaultFrom";
                        public static final String ConnectionTimeout = "connectionTimeout";
                        public static final String OperationTimeout = "operationTimeout";
                        public static final String SocksHost = "socksHost";
                        public static final String SocksPort = "socksPort";
                        public static final String FileRepository = "fileRepository";
                      }
                    
                    
                    }