cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - New to the community? Learn how to post a question and get help from PTC and industry experts! X

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

vsharma-21
3-Newcomer

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]

8 REPLIES 8
supandey
19-Tanzanite
(To:vsharma-21)

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?

Sushant, I am facing this error at the time of testing SendMessageWithImage.

supandey
19-Tanzanite
(To:vsharma-21)

Could you share screenshot how you are testing it and the values you are putting in to test the service?

Vaibhav Sharma​,

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

Ankit Gupta

It is a custom extension.

Vaibhav Sharma​,

Please share the definition/code for SendMessageWithImage service.

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 = new InternetAddress(addresses.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 = new InternetAddress(addresses.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 = new InternetAddress(addresses.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";

  }

}

I thing I found your problem.

In your service definition, the name "SendMessageWithImage" is not the java method name (SendMessage)

Fix the name, re-import the extension and clean the cache or restart the server, it should work

Regards,

Cyril

  1. @ThingworxServiceDefinition(name="SendMessageWithImage", description="Send a simple textual e-mail message with an image attachment"
  2.   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{ 
  3.  


Announcements


Top Tags