Problem trying to consume webservice on android

0

I'm trying to do a query through the android in a firebird database, the webservice is working perfectly however when trying to query through the application it generates the following error:

05-31 13:55:52.339 4062-4062/br.com.realsysten.restaurante E/AndroidRuntime: FATAL EXCEPTION: main
Process: br.com.realsysten.restaurante, PID: 4062                                                                             java.lang.RuntimeException: Unable to start activity ComponentInfo{br.com.realsysten.restaurante/br.com.realsysten.restaurante.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.util.ArrayList.toString()' on a null object reference
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
 at android.app.ActivityThread.-wrap11(ActivityThread.java)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
 at android.os.Handler.dispatchMessage(Handler.java:102)
 at android.os.Looper.loop(Looper.java:148)
 at android.app.ActivityThread.main(ActivityThread.java:5417)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.util.ArrayList.toString()' on a null object reference
 at br.com.realsysten.restaurante.MainActivity.onCreate(MainActivity.java:26)
 at android.app.Activity.performCreate(Activity.java:6237)
 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
 at android.app.ActivityThread.-wrap11(ActivityThread.java) 
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
 at android.os.Handler.dispatchMessage(Handler.java:102) 
 at android.os.Looper.loop(Looper.java:148) 
 at android.app.ActivityThread.main(ActivityThread.java:5417) 
 at java.lang.reflect.Method.invoke(Native Method) 
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

I have the following classes:

Table:

package br.com.realsysten.restaurante;

import java.sql.Date;

/**
 * Created by Vitor on 31/05/2016.
 */
public class Mesa {

    private int id;
    private String barras;
    private String tipo;
    private Date data;
    private int lugares;
    private String situacao;
    private String descricao;
    private double credito;

    public Mesa(){
    }

    public Mesa(int id, String barras, String tipo, Date data, int lugares, String situacao, String descricao,
                double credito) {
        super();
        this.id = id;
        this.barras = barras;
        this.tipo = tipo;
        this.data = data;
        this.lugares = lugares;
        this.situacao = situacao;
        this.descricao = descricao;
        this.credito = credito;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getBarras() {
        return barras;
    }

    public void setBarras(String barras) {
        this.barras = barras;
    }

    public String getTipo() {
        return tipo;
    }

    public void setTipo(String tipo) {
        this.tipo = tipo;
    }

    public Date getData() {
        return data;
    }

    public void setData(Date data) {
        this.data = data;
    }

    public int getLugares() {
        return lugares;
    }

    public void setLugares(int lugares) {
        this.lugares = lugares;
    }

    public String getSituacao() {
        return situacao;
    }

    public void setSituacao(String situacao) {
        this.situacao = situacao;
    }

    public String getDescricao() {
        return descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }

    public double getCredito() {
        return credito;
    }

    public void setCredito(double credito) {
        this.credito = credito;
    }

    @Override
    public String toString() {
        return "Mesa{" +
                "id=" + id +
                ", barras='" + barras + '\'' +
                ", tipo='" + tipo + '\'' +
                ", data=" + data +
                ", lugares=" + lugares +
                ", situacao='" + situacao + '\'' +
                ", descricao='" + descricao + '\'' +
                ", credito=" + credito +
                '}';
    }
}

MesaDAO:

package br.com.realsysten.restaurante;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Vector;

/**
 * Created by Vitor on 31/05/2016.
 */
public class MesaDAO {

    private static final String URL = "http://192.168.2.236:8080/SigadmWS/services/MesaDAO?wsdl";
    private static final String NAMESPACE = "http://SigadmWS.realsysten.com.br";

    private static final String BUSCAR_TODOS = "buscarTodos";

    public ArrayList<Mesa> buscarTodos(){
        ArrayList<Mesa> lista = new ArrayList<Mesa>();

        SoapObject buscarMesa = new SoapObject(NAMESPACE, BUSCAR_TODOS);

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12);
        envelope.setOutputSoapObject(buscarMesa);
        envelope.implicitTypes = true;

        HttpTransportSE htpp = new HttpTransportSE(URL);

        try {
            htpp.call("urn:" + BUSCAR_TODOS, envelope);
            Vector<SoapObject> resposta = (Vector<SoapObject>) envelope.getResponse();
            for(SoapObject soapObject : resposta){
                Mesa mesa = new Mesa();
                SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

                mesa.setId(Integer.parseInt(soapObject.getProperty("CON_CODIGO").toString()));
                mesa.setBarras(soapObject.getProperty("CON_CODIGO_BARRAS").toString());
                mesa.setTipo(soapObject.getProperty("CON_TIPO").toString());
                mesa.setData((java.sql.Date) format.parse(soapObject.getProperty("CON_DATA").toString()));
                mesa.setLugares(Integer.parseInt(soapObject.getProperty("CON_QTDE_LUGARES").toString()));
                mesa.setSituacao(soapObject.getProperty("CON_SITUACAO").toString());
                mesa.setDescricao(soapObject.getProperty("CON_DESCRICAO").toString());
                mesa.setCredito(Double.parseDouble(soapObject.getProperty("CON_VLR_CREDITO").toString()));

                lista.add(mesa);
            }
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }

        return lista;
    }
}

Main:

package br.com.realsysten.restaurante;

import android.os.Build;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(Build.VERSION.SDK_INT > 9){
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }

        MesaDAO dao = new MesaDAO();

        ArrayList<Mesa> lista = dao.buscarTodos();
        Log.d("SigadmWS", lista.toString());
    }
}

Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="br.com.realsysten.restaurante">

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

When running debug, the error occurs on the following line:

htpp.call("urn:" + BUSCAR_TODOS, envelope);

Does anyone know why?

thank you from ja

    
asked by anonymous 31.05.2016 / 16:02

1 answer

2

Dear, the error is in the request for some reason. After a few years working with KSoap, I have created a certain structure and I want to teach you how to solve this problem in an organized way with lean code and no control couplings.

It would be very important that you do not mix the request results handling with the service call as you are doing in your tests, so I'll send you some code snippets to help you organize your code.

In addition, it is highly recommended not to run strict mode, unless they are tests. But implement the AsyncTasks correctly ok.

Consider creating a class, for example, Send.java with the implementation of the call method:

/**
     * Método que chama uma operação webservices
     * 
     * @param properties
     *            - Propriedades (Parâmetros de entrada)
     * @param namespace
     *            - namespace
     * @param methodName
     *            - método
     * @param url
     *            - url
     * @param action
     *            - action
     * @return InputStream.
     */
    public InputStream call(String url, String namespace, String methodName, String action, ArrayList<PropertyInfo> properties) throws XmlPullParserException, IOException {
        InputStream resultado;
        SoapObject request = new SoapObject(namespace, methodName);

        if (properties != null) {
            // Adicionando dinamicamente as propriedades.
            for (PropertyInfo property : properties) {
                request.addProperty(property);
            }
        }

        SoapSerializationEnvelope envp = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envp.dotNet = false;

        MarshalDouble md = new MarshalDouble();
        md.register(envp);

        envp.setOutputSoapObject(request);

        try {
            //Adicionando um timeout de 2 minutos.
            HttpTransportSE androidHttpTransport = new HttpTransportSE(url, 60000);
            androidHttpTransport.debug = true;

            // System.setProperty("http.keepAlive", "false");
            androidHttpTransport.call(action, envp);

            Object response = envp.getResponse();
            resultado = new ByteArrayInputStream(response.toString().getBytes("UTF-8"));
            Log.i("Send", "RESULTADO: " + resultado);

        } catch (IOException | XmlPullParserException e) {
            Log.e("Send", e.toString());
            throw e;
        }
        return resultado;
    }

Next, create the classes separately to work with each of your WebMethods (you can group the methods by affinity - subject). Here I have an example called WSInformacoesX (rename of the real) that just calls the method desired by the constant in the call call method of the Send class.

public class WSInformacoesX {

    private Send wsSender;
    private PropertyInfo pCODIGOUSUARIO;

    public WSInformacoesX() {
        wsSender = new Send();
    }

    public InputStream getInformacoesX(String codigousuario) throws XmlPullParserException, IOException {

        ArrayList<PropertyInfo> propriedades = new ArrayList<>();

        pCODIGOUSUARIO = new PropertyInfo();
        pCODIGOUSUARIO.setName("CODIGOUSUARIO");
        pCODIGOUSUARIO.setValue(codigousuario);
        pCODIGOUSUARIO.setType(String.class);
        propriedades.add(pCODIGOUSUARIO);

        return wsSender.call(WSConfig.SOAP_URL, WSConfig.SOAP_NAMESPACE, WSConfig.SOAP_METHOD_GETINFORMACOESX, WSConfig.SOAP_ACTION_GETINFORMACOESX, propriedades);
    }
}

In addition, it is important to note that for each result you can have a specific, well-organized parser, parsing correctly for each type of POJO object you have, analyzing the XML, for example:

public class ParserResultadoOperacao {

    private ResultadoOperacao resultado;
    private String text;

    public ResultadoOperacao parse(InputStream is) throws XmlPullParserException, IOException {

        XmlPullParserFactory factory;
        XmlPullParser parser;

        factory = XmlPullParserFactory.newInstance();
        factory.setNamespaceAware(true);
        parser = factory.newPullParser();

        parser.setInput(is, null);

        int eventType = parser.getEventType();
        while (eventType != XmlPullParser.END_DOCUMENT) {
            String tagname = parser.getName();
            switch (eventType) {
            case XmlPullParser.START_TAG:
                if (tagname.equalsIgnoreCase("app")) {
                    resultado = new ResultadoOperacao();
                }
                break;
            case XmlPullParser.TEXT:
                text = parser.getText();
                break;
            case XmlPullParser.END_TAG:
                if (tagname.equalsIgnoreCase("status")) {
                    resultado.setStatus(Long.parseLong(text));
                } else if (tagname.equalsIgnoreCase("mensagem")) {
                    if (text != null) {
                        resultado.setMensagem(text);
                    }
                }
                break;
            default:
                break;
            }
            eventType = parser.next();
        }

        return resultado;
    }
}

Of course, always try to adjust your parsers to form that does not unnecessarily write code.

Finally, the error may be because the method is not being found. Set a class for example called WSConfig where you put all methods (and is used above in the specific call class), for example:

public static String SOAP_URL = "http://www.xpto.com/Services.php";

public static String SOAP_ACTION_GETINFORMACOESX = "urn:server#getInformacoesX";
public static String SOAP_METHOD_GETINFORMACOESX = "getInformacoesX";

I hope to have helped and good codes!

    
31.05.2016 / 16:30