0

I am using Google AppEngine with Java.
I am using SendGrid API to send emails. So I downloaded the SendGrid library (https://github.com/sendgrid/sendgrid-java).
I wrote a test application outside AppEngine with Java and it is sending emails properly.
When I tried to run the application with AppEngine, it is showing this error:

java.lang.NoClassDefFoundError: org/apache/http/ssl/SSLContexts
    at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:966)
    at org.apache.http.impl.client.HttpClients.createDefault(HttpClients.java:58)
    at com.sendgrid.Client.<init>(Client.java:55)
    at com.sendgrid.SendGrid.<init>(SendGrid.java:29)
    at com.fms.advocacy.AdvocacyMail.send(AdvocacyMail.java:40)
    at com.fms.advocacy.AdvocacyMail.send(AdvocacyMail.java:36)
    at com.fms.advocacy.AdvocacyMail.send(AdvocacyMail.java:32)
    at com.fms.advocacy.api.auth.AuthenticationApi.forgotPassword(AuthenticationApi.java:186)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:130)
    at com.google.api.server.spi.SystemService.invokeServiceMethod(SystemService.java:363)
    at com.google.api.server.spi.SystemServiceServlet.execute(SystemServiceServlet.java:113)
    at com.google.api.server.spi.SystemServiceServlet.doPost(SystemServiceServlet.java:71)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
    at com.fms.advocacy.filters.AccessRuleFilter.doFilter(AccessRuleFilter.java:49)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.fms.advocacy.filters.AuthFilter.doFilter(AuthFilter.java:32)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.fms.advocacy.filters.ErrorHandlerFilter.doFilter(ErrorHandlerFilter.java:36)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:128)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:50)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366)
    at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349)
    at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:98)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:512)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

Can anybody resolve the issue?

This is my pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>

    <groupId>com.fms</groupId>
    <artifactId>advocacy</artifactId>

    <properties>
        <app.id>xyz-abc</app.id>
        <app.version>1</app.version>
        <appengine.version>1.9.42</appengine.version>
        <gcloud.plugin.version>2.0.9.74.v20150814</gcloud.plugin.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.showDeprecation>true</maven.compiler.showDeprecation>
    </properties>

    <prerequisites>
        <maven>3.1.0</maven>
    </prerequisites>

    <dependencies>
        <!-- Compile/runtime dependencies --> 
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>   
        <dependency>
            <groupId>com.google.appengine</groupId>
            <artifactId>appengine-api-1.0-sdk</artifactId>
            <version>${appengine.version}</version>
        </dependency>  
        <dependency>
            <groupId>com.sendgrid</groupId>
            <artifactId>sendgrid-java</artifactId>
            <version>3.0.8</version>
            <type>jar</type>
        </dependency>  
    </dependencies>

    <build>
        <!-- for hot reload of the web application -->
        <outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <version>3.1</version>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archiveClasses>true</archiveClasses>
                    <webResources>
                        <!-- in order to interpolate version from pom into appengine-web.xml -->
                        <resource>
                            <directory>${basedir}/src/main/webapp/WEB-INF</directory>
                            <filtering>true</filtering>
                            <targetPath>WEB-INF</targetPath>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>

            <plugin>
                <groupId>com.google.appengine</groupId>
                <artifactId>appengine-maven-plugin</artifactId>
                <version>${appengine.version}</version>
                <configuration>
                    <enableJarClasses>false</enableJarClasses>
                    <version>${app.version}</version>
                    <address>0.0.0.0</address>
                    <port>8888</port>
                    <jvmFlags>
                        <jvmFlag>-agentlib:jdwp=transport=dt_socket,address=8001,server=y,suspend=n</jvmFlag>
                    </jvmFlags>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.google.appengine</groupId>
                <artifactId>gcloud-maven-plugin</artifactId>
                <version>${gcloud.plugin.version}</version>
                <configuration>
                    <set_default>true</set_default>
                </configuration>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>versions-maven-plugin</artifactId>
                    <version>2.1</version>
                    <executions>
                        <execution>
                            <phase>compile</phase>
                            <goals>
                                <goal>display-dependency-updates</goal>
                                <goal>display-plugin-updates</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <!--This plugin's configuration is used to store Eclipse m2e settings 
                    only. It has no influence on the Maven build itself. -->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>
                                            org.codehaus.mojo
                                        </groupId>
                                        <artifactId>
                                            versions-maven-plugin
                                        </artifactId>
                                        <versionRange>
                                            [2.1,)
                                        </versionRange>
                                        <goals>
                                            <goal>
                                                display-plugin-updates
                                            </goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>
Harikrishnan
  • 3,664
  • 7
  • 48
  • 77

2 Answers2

1

Sendgrid depends on the Apache httpclient which is potentially problematic on GAE.

They have a special lib for GAE:

https://github.com/sendgrid/sendgrid-google-java

See also:

https://cloud.google.com/appengine/docs/java/mail/sendgrid

So use sendgrid-google-java instead of sendgrid-java.

Christiaan
  • 2,637
  • 21
  • 26
  • I tried that. but it is very basic. Also no documentation available for attachments and templates – Harikrishnan Aug 16 '16 at 09:54
  • It seems to be just a wrapper around Sendgrid's v2 web api: https://sendgrid.com/docs/API_Reference/Web_API/using_the_web_api.html so you could use the documentation there to see how to send attachments etc. It might actually be better to just use the v3 api right away and not use this sengrid-google-java lib itself. Just make sure to use java.net.HttpURLConnection or Google's own httpclient. – Christiaan Aug 16 '16 at 10:04
  • 1
    OK. I will try that. Thanks for the reply – Harikrishnan Aug 16 '16 at 10:14
0

Looks like you miss the httpclient<version>.jar in your classpath.

For gradle add the following dependency:

compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.2'
Jens
  • 67,715
  • 15
  • 98
  • 113
  • Should this not be a comment instead of an answer? – ppeterka Aug 16 '16 at 08:44
  • @ppeterka No. It is the answer – Jens Aug 16 '16 at 08:45
  • Are you sure? The question is completely incomplete... Also, OP wrote `and it is sending emails properly` so on the his computer, stuff seems to work, so *that* classpath is OK. There is something wrong on the classpath on AppEngine - like the version conflict in [this question](http://stackoverflow.com/questions/36914117/httpclient-jar-conflicts-how-to-fix-it). – ppeterka Aug 16 '16 at 08:47
  • In my working program I only added the maven repository for app engine and Sendgrid Java client. https://mvnrepository.com/artifact/com.sendgrid/sendgrid-java/3.0.8 Also, when I add this repository will maven automatically download other required libraries automatically? isn't it the whole idea of maven? – Harikrishnan Aug 16 '16 at 09:07
  • @Harikrishnan Yes it is the idea of maven. But it can be that the developer not want to add some jars, because of different Versions and so on. So it is possible, that you have to add this manually – Jens Aug 16 '16 at 09:23
  • I added it now (https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient/4.5.2), but still showing this error. Caused by: java.lang.ClassNotFoundException: org.apache.http.ssl.SSLContexts – Harikrishnan Aug 16 '16 at 09:25
  • Show the changes you made and make sure that the file is part of your application – Jens Aug 16 '16 at 09:27
  • @Harikrishnan Looks ok. Can you verify if the jar contains the missing class? – Jens Aug 16 '16 at 09:43
  • No. that class is not there – Harikrishnan Aug 16 '16 at 09:52