Problem when trying to consume the webservice on android

Asked

Viewed 214 times

0

I am trying to make a query through android in a database Firebird, the webservice is working perfectly but when trying to make the 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 +
                '}';
    }
}

Same:

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 the debug, the error occurs on the following line:

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

someone knows why?

thanks since you

1 answer

2


Dear man, the mistake is in the requisition for a reason. After a few years working with Ksoap, I created a certain structure and wish to teach you how to solve this problem in an organized way with a lean code and no control couplings.

It would be very important not to mix the treatment of the results of the request with the service call as you are doing in your tests, for this I will send you some code fragments to assist you in the organization of your code.

Also, it is highly not recommended to run Strict mode unless they are tests. But implement the Asynctasks correctly ok.

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

/**
     * 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;
    }

Then create separate classes to work with each of your Webmethods (you can group the methods by affinity - subject). Here I have an example called Wsinformacoesx (renamed from the real) that calls just the method desired by the constant in the 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);
    }
}

Also, it is important to note that for each result you can have a clear and well organized specific parser, performing the 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 do not write unnecessarily code.

Finally, the error may be because the method is not being found. Define a class for example called Wsconfig in which 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 I’ve helped and good codes!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.