Neste tutorial pretendo mostrar de forma simples como criar um Web Service em Java utilizando o NetBeans e uma aplicação cliente para consumir o serviço no Android. O Web Service vai implementar uma operação que deverá retornar um array de objetos. Na aplicação Android esse array será recebido e utilizado para preencher uma lista de itens (ListView).
Ferramentas utilizadas:
- NetBeans 7.1 + Tomcat 7 (servidor)
- Eclipse + ADT - Android Developer Tools v21.0.1-543035 (cliente)
Criando o Web Service
Não vou entrar em detalhes sobre a criação da aplicação no NetBeans porque já existe um bom tutorial disponível aqui. Após criar o projeto, crie também uma classe para o objeto que será retornado. Para fins de exemplo vou utilizar a seguinte classe:
public class Fornecedor {
int codigo;
String razaoSocial;
String cpfCnpj;
public Fornecedor() {
}
public Fornecedor(int codigo, String razaoSocial, String cpfCnpj) {
this.codigo = codigo;
this.razaoSocial = razaoSocial;
this.cpfCnpj = cpfCnpj;
}
public int getCodigo() {
return codigo;
}
public void setCodigo(int codigo) {
this.codigo = codigo;
}
public String getCpfCnpj() {
return cpfCnpj;
}
public void setCpfCnpj(String cpfCnpj) {
this.cpfCnpj = cpfCnpj;
}
public String getRazaoSocial() {
return razaoSocial;
}
public void setRazaoSocial(String razaoSocial) {
this.razaoSocial = razaoSocial;
}
@Override
public String toString() {
return getCodigo() + ". " + getRazaoSocial();
}
}
É importante que sua classe tenha um construtor padrão, sem argumentos. Pode parecer inútil mas o Tomcat não vai implantar o projeto sem ele. O método toString deverá ser sobrescrito na classe, mas isto será útil apenas na aplicação cliente ao preencher a lista, pois será utilizada a mesma classe.
Seguindo o tutorial que foi sugerido, você deve criar uma operação que não receberá parâmetros e que a saída será do tipo List<Fornecedor>. Para o exemplo vou chamar esta operação de getFornecedores. O código deverá ser parecido com este:
Seguindo o tutorial que foi sugerido, você deve criar uma operação que não receberá parâmetros e que a saída será do tipo List<Fornecedor>. Para o exemplo vou chamar esta operação de getFornecedores. O código deverá ser parecido com este:
@WebService(serviceName = "GetFornecedores")
public class GetFornecedores {
@WebMethod(operationName = "getFornecedores")
public List<Fornecedor> getFornecedores() {
List<Fornecedor> listFornecedores = new ArrayList<Fornecedor>();
listFornecedores.add(new Fornecedor(1, "Fornecedor 1", "0123456789"));
listFornecedores.add(new Fornecedor(2, "Fornecedor 2", "0123456789"));
listFornecedores.add(new Fornecedor(3, "Fornecedor 3", "0123456789"));
return listFornecedores;
}
}
Após implantar e executar o projeto, o arquivo wsdl pode ser acessado através do browser, de acordo com suas configurações:
http://localhost:8080/TestWSApp/GetFornecedores?wsdl
Com o projeto rodando vamos para a segunda parte.
Criando o cliente Android
Crie um projeto no Eclipse com uma Activity principal e adicione a lib ksoap2 no Build Path. Copie a classe Fornecedor citada anteriormente e cole no pacote do projeto. Então crie uma classe chamada ConexaoWS com o seguinte código:
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
public class ConexaoWS {
private static final String NAMESPACE = "http://testws.me.org/";
private static final String METHOD_NAME = "getFornecedores";
private static final String SOAP_ACTION = "http://testws.me.org/getFornecedores";
private static final String URL = "http://10.1.0.116:8080/TestWSApp/GetFornecedores?wsdl";
public Fornecedor[] getFornecedores() throws Exception {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE ht = new HttpTransportSE(URL);
ht.call(SOAP_ACTION, envelope);
SoapObject response = (SoapObject) envelope.bodyIn;
Fornecedor[] fornecedores = new Fornecedor[response.getPropertyCount()];
for (int c = 0; c < fornecedores.length; c++) {
SoapObject soapObject = (SoapObject) response.getProperty(c);
Fornecedor f = new Fornecedor();
f.codigo = Integer.parseInt(soapObject.getProperty(0).toString());
f.cpfCnpj = soapObject.getProperty(1).toString();
f.razaoSocial = soapObject.getProperty(2).toString();
fornecedores[c] = f;
}
return fornecedores;
}
}
As principais alterações a serem feitas são nas constantes:
- NAMESPACE: Pode ser encontrado no arquivo wsdl, mas normalmente é "http://" + pacote + "/"
- METHOD_NAME: Mesmo nome dado a operação
- SOAP_ACTION: NAMESPACE + METHOD_NAME
- URL: Endereço do arquivo wsdl (nos meus testes a conexão foi recusada quando utilizei localhost ou 127.0.0.1, portanto use o IP real da sua máquina)
Com isto fica faltando o layout da aplicação e a chamada do método. Para o layout utilize a seguinte definição:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
</ListView>
</RelativeLayout>
E para a classe principal utilize o seguinte código:
public class MainActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Operações de rede não podem ser realizadas na thread principal
new MyAsyncTask().execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
private class MyAsyncTask extends AsyncTask<Void, Void, Fornecedor[]> {
boolean erro = false;
private final ProgressDialog dialog = new ProgressDialog(
MainActivity.this);
@Override
protected void onProgressUpdate(Void... values) {
this.dialog.setMessage("Aguarde...");
this.dialog.show();
}
@Override
protected Fornecedor[] doInBackground(Void... params) {
Fornecedor[] retorno = null;
try {
ConexaoWS conexao = new ConexaoWS();
retorno = conexao.getFornecedores();
} catch (Exception e) {
erro = true;
e.printStackTrace();
}
return retorno;
}
@Override
protected void onPostExecute(Fornecedor[] result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
if (erro == false) {
List<Fornecedor> listaFornecedores = Arrays.asList(result);
ArrayAdapter<Fornecedor> adapter = new ArrayAdapter<Fornecedor>(
MainActivity.this, android.R.layout.simple_list_item_1,
listaFornecedores);
setListAdapter(adapter);
} else {
Toast.makeText(MainActivity.this,
"Ocorreu um erro ao acessar o Web Service.",
Toast.LENGTH_LONG).show();
}
}
}
}
Se você é leigo em programação para Android, recomendo que procure entender como funcionam as classes ListActivity e AsyncTask para melhor compreensão do exemplo. O resultado da aplicação será este:

Tenho algumas dúvidas à respeito desse seu exemplo, a class Fornecedor e a class GetFornecedor, você criou elas no Netbeans é isso? Dentro do mesmo pacote do WebService? Ou você criou só o WS no NetBeans e o resto no Eclipse?
ResponderExcluirE, no caso do WebService que foi criado, se for feito baseado no do link que você passou, no lugar de i, j e k foi declarado, código, razãoSocial e cnpj?
É isso?
Roberta, a parte do WebService é feita totalmente no NetBeans. O tutorial que estou sugerindo no texto é apenas pra ter uma idéia de como criar um WebService. No exemplo do tutorial ele recebe i + j e retorna k, que é a soma dos dois. No meu exemplo não recebe nenhum parâmetro, apenas retorna uma lista do tipo List<Fornecedor>. Fornecedor é uma classe modelo, de acordo com padrão MVC. Deu pra entender?
Excluirparabéns, ótimo tuto.
ResponderExcluirObrigado!
ExcluirCara, simplesmente obrigado...
ResponderExcluirPor nada!
ExcluirBoa noite amigo, estou tentando o contrario, tenho que enviar um array para ser consumido no WS, so erro , me ajude por favor amigo
ResponderExcluirAlexandre, entre em contato no e-mail marciosouzajunior@gmail.com
Excluir