0

I have a dynamic web project that contains a web service. I have exported it as a WAR file and placed it in the webapps directory of tomcat. Tomcat shows that the web app is running. When I attempt to invoke one of the operations of my service, I get the following exception:

java.lang.NullPointerException
    sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
    java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1629)
    org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:461)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:931)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    java.lang.Thread.run(Thread.java:680)

Any idea what this means?

Here's my class the defines the web service:

package webservice;

import java.sql.*;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.core.MediaType;

@Path("/operations")
public class NotifyWebService {

    @Path("/insertNewPatron")
    @GET

    public String insertNewPatron(@QueryParam("cardNumber")String cardNumber,
                                    @QueryParam("pin") String pin,
                                    @QueryParam("nickname") String nickname,
                                    @QueryParam("deviceID")String deviceID) throws Exception {


        String connectionUrl = "jdbc:sqlserver://mssql.acpl.lib.in.us:1433;" +
                   "databaseName=MobileNotify;user=Mobile_Notification_User;password=xxxxxxx;";




            Connection c = DriverManager.getConnection(connectionUrl);

            String insertPatronStatement = "INSERT INTO dbo.Patron VALUES ('"+cardNumber+"','"+pin+"','"+nickname+"')";
            String insertDeviceOwner = "INSERT INTO dbo.DeviceOwner VALUES ('"+deviceID+"','"+cardNumber+"')";
            Statement state = null;

            state = c.createStatement();
            state.executeUpdate(insertPatronStatement);
            state.executeUpdate(insertDeviceOwner);


            c.close();


            return "true";
    }


    @Path("/initializeDevice")
    @GET

    public String initializeDevice( @QueryParam("deviceID")String deviceID) throws Exception{

        String connectionUrl = "jdbc:sqlserver://mssql.acpl.lib.in.us:1433;" +
                   "databaseName=MobileNotify;user=Mobile_Notification_User;password=xxxxxx;";


        Connection c = DriverManager.getConnection(connectionUrl);

        String insertDeviceStatement = "INSERT INTO dbo.Devices VALUES ('"+deviceID+"',1,3,1,3)";
        Statement state = c.createStatement();
        state.executeUpdate(insertDeviceStatement);


        return "true";
    }


    @Path("/updateDevicePreferences")
    @GET

    public String updateDevicePreferences(@QueryParam("deviceID") String deviceID, 
                                            @QueryParam("dueDateNotice")String dueDateNotice,
                                            @QueryParam("dueDateNoticeAdvance") String dueDateNoticeAdvance,
                                            @QueryParam("holdsNotice") String holdsNotice, 
                                            @QueryParam("eventNoticeAdvance")String eventNoticeAdvance) throws Exception{
        String connectionUrl = "jdbc:sqlserver://mssql.acpl.lib.in.us:1433;" +
                   "databaseName=MobileNotify;user=Mobile_Notification_User;password=xxxxxx;";


        Connection c = DriverManager.getConnection(connectionUrl);

        String updateDeviceStatement = "UPDATE dbo.Devices SET dueDateNotice="+dueDateNotice+", dueDateNoticeAdvance="+dueDateNoticeAdvance
                                    +", holdsNotice="+holdsNotice+", eventNoticeAdvance="+eventNoticeAdvance+" WHERE deviceID='"+deviceID+"'";
        Statement state = c.createStatement();
        state.executeUpdate(updateDeviceStatement);

        return "true";
    }


    @Path("/removeUser")
    @GET

    public String removeUser(@QueryParam("cardNumber")String cardNumber) throws Exception{
        String connectionUrl = "jdbc:sqlserver://mssql.acpl.lib.in.us:1433;" +
                   "databaseName=MobileNotify;user=Mobile_Notification_User;password=xxxxxx;";


        Connection c = DriverManager.getConnection(connectionUrl);

        String removeStatement = "DELETE FROM dbo.Patron WHERE cardNumber='"+cardNumber+"'";

        Statement state = c.createStatement();
        state.executeUpdate(removeStatement);




        return "true";
    }

    @Path("/addEvent")
    @GET

    public String addEvent(@QueryParam("deviceID")String deviceID, @QueryParam("eventID")String eventID) throws Exception{

        String connectionUrl = "jdbc:sqlserver://mssql.acpl.lib.in.us:1433;" +
                   "databaseName=MobileNotify;user=Mobile_Notification_User;password=xxxxx;";


        Connection c = DriverManager.getConnection(connectionUrl);

        String eventStatement = "INSERT INTO dbo.Events VALUES ('"+deviceID+"','"+eventID+"')";
        Statement state = c.createStatement();
        state.executeUpdate(eventStatement);


        return "true";
    }

    @Path("/removeEvent")
    @GET

    public String removeEvent(@QueryParam("deviceID")String deviceID, @QueryParam("eventID")String eventID) throws Exception{

        String connectionUrl = "jdbc:sqlserver://mssql.acpl.lib.in.us:1433;" +
                   "databaseName=MobileNotify;user=Mobile_Notification_User;password=xxxxx;";


        Connection c = DriverManager.getConnection(connectionUrl);

        String eventStatement = "DELETE FROM dbo.Events WHERE deviceID='"+deviceID+"' AND eventID='"+eventID+"'";
        Statement state = c.createStatement();
        state.executeUpdate(eventStatement);


        return "true";
    }

    @Path("/removeAllEvents")
    @GET

    public String removeAllEvents(@QueryParam("deviceID")String deviceID) throws Exception{

        String connectionUrl = "jdbc:sqlserver://mssql.acpl.lib.in.us:1433;" +
                   "databaseName=MobileNotify;user=Mobile_Notification_User;password=xxxx;";


        Connection c = DriverManager.getConnection(connectionUrl);

        String eventStatement = "DELETE FROM dbo.Events WHERE deviceID='"+deviceID+"'";
        Statement state = c.createStatement();
        state.executeUpdate(eventStatement);


        return "true";
    }
}

Here's my web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>APNS_WebService</display-name>
   <servlet>
        <servlet-name>javax.ws.rs.core.Application</servlet-name>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>javax.ws.rs.core.Application</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

Let me know if more information is required!

1 Answer 1

2

I believe that the cause of your NPE is the lack of a <servlet-class> element in your <servlet> block. However, deciding what the servlet-class should be raises a bigger problem...

It looks like you have not chosen a JAX-RS framework. See JAX-RS Frameworks for insight on various alternatives.

I am currently using Jersey. A typical web.xml for Jersey might contain:

  <servlet>
    <servlet-name>WebService</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
       <param-name>com.sun.jersey.config.property.packages</param-name>
       <param-value>webservice</param-value>
    </init-param>
    <init-param>
      <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
      <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>WebService</servlet-name>
    <url-pattern>/api/rest/*</url-pattern>
  </servlet-mapping>

For many JAX-RS frameworks, the choice of framework will determine what you should enter as the <servlet-class>

Also note that since your root resource is in package webservice, I set the com.sun.jersey.config.property.packages parameter to webservice so Jersey will scan your package for any JAX-RS annotated classes.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, that did it! I thought I had a web.xml similar to that previously but I guess I was wrong!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.