Arquivo do autor:Marcos

Como deixar o Eclipse mais rápido

Algumas versões do eclipse vem com dois plugins que eu não utilizo e são bem lentos para ficarem lá, consumindo meu tempo.

Um deles é o JPA/Dali, que tem um bug que exibe diversas vezes a mensagem: “JPA Project Change Event Handler (waiting)”.
Para remove-lo, entre no diretório do seu eclipse e faça o seguinte:

mkdir disabled disabled/features disabled/plugins

mv plugins/org.eclipse.jpt.* disabled/plugins
mv features/org.eclipse.jpt.* disabled/features

Outro plugin, é o Egit, que fica sincronizando os arquivos locais com o repositório git.
Para remove-lo, também, entre no diretório do seu eclipse e faça:

mkdir disabled disabled/features disabled/plugins

mv plugins/*jgit* disabled/plugins
mv plugins/*egit* disabled/plugins
mv features/*egit* disabled/features

Estas dicas foram tiradas daqui:
http://stackoverflow.com/questions/19649847/eclipse-kepler-jpa-project-change-event-handler-waiting
http://stackoverflow.com/questions/17408483/how-to-remove-egit-from-eclipse-kepler

Anúncios

Manipulação de dados com JDBC, com banco MySQL

A forma mais simples de manipular os dados de um banco em Java é utilizar API JDBC. Para demonstrar alguns exemplos de utilização, usaremos o banco de dados MySQL, com a tabela abaixo:

CREATE TABLE BOOK
(
ID bigint PRIMARY KEY NOT NULL,
DESCRIPTION text,
ILUSTRATIONS bit DEFAULT 0,
ISBN varchar(255),
NBOFPAGE int,
PRICE real,
TITLE varchar(255) NOT NULL
);
CREATE UNIQUE INDEX PRIMARY ON BOOK(ID);

Para executar um comando no banco é preciso adicionar o driver do banco no classpath e então uma criar uma conexão:

Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://host/database";
String user = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url,user, password);

Feito isto, é necessário criar um Statement com o comando SQL a ser executado:

Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select title from book");

E depois percorrer o ResultSet com os dados:

while(resultSet.next()){
    System.out.println(resultSet.getString("title"));
}

Além do Statement é possível criar um PreparedStatement para informar parâmetros para a consulta:

PreparedStatement preparedStatement = connection.prepareStatement("select title from book where id=?");
preparedStatement.setInt(1, 25346);
ResultSet anotherResultSet = preparedStatement.executeQuery();
while(anotherResultSet.next()){
    System.out.println(anotherResultSet.getString("title"));
}

Para executar um comando para inserir ou fazer atualização de um registro, basta utilizar o PreparedStatement e ao final chamar o método executeUpdate, que retornará o número de linhas afetadas pelo comando:

String sql = "insert into book (ID, TITLE, PRICE, DESCRIPTION, ISBN, ILUSTRATIONS, NBOFPAGE) values (?,?,?,?,?,?,?)";

PreparedStatement anotherPreparedStatement = connection.prepareStatement(sql);
anotherPreparedStatement.setLong(1, 13523L);
anotherPreparedStatement.setString(2, "The hitchhicker's guide to the galaxy");
anotherPreparedStatement.setFloat(3, 12.5F);
anotherPreparedStatement.setString(4, "Science Fiction");
anotherPreparedStatement.setString(5, "2329-1341-32918");
anotherPreparedStatement.setBoolean(6, false);
anotherPreparedStatement.setInt(7, 354);

int result = anotherPreparedStatement.executeUpdate();
System.out.println(result);

As exeções lançadas pelos códigos acima foram omitidas, para melhor entendimento.
A seguir a classe por completo:

public class JDBCSample {

	public static void main(String[] args) {
		try {			
			Class.forName("com.mysql.jdbc.Driver");
			String url = "jdbc:mysql://host/database";
			String user = "root";
			String password = "root";
			
			Connection connection = DriverManager.getConnection(url,user, password);
			
			Statement statement = connection.createStatement();
			ResultSet resultSet = statement.executeQuery("select title from book");
			
			while(resultSet.next()){
				System.out.println(resultSet.getString("title"));
			}
			
			PreparedStatement preparedStatement = connection.prepareStatement("select title from book where id=?");
			preparedStatement.setInt(1, 25346);
			ResultSet anotherResultSet = preparedStatement.executeQuery();
			
			while(anotherResultSet.next()){
				System.out.println(anotherResultSet.getString("title"));
			}
			
			String sql = "insert into book (ID, TITLE, PRICE, DESCRIPTION, ISBN, ILUSTRATIONS, NBOFPAGE) values (?,?,?,?,?,?,?)";
			PreparedStatement anotherPreparedStatement = connection.prepareStatement(sql);
			anotherPreparedStatement.setLong(1, 13523L);
			anotherPreparedStatement.setString(2, "The hitchhicker's guide to the galaxy");
			anotherPreparedStatement.setFloat(3, 12.5F);
			anotherPreparedStatement.setString(4, "Science Fiction");
			anotherPreparedStatement.setString(5, "2329-1341-32918");
			anotherPreparedStatement.setBoolean(6, false);
			anotherPreparedStatement.setInt(7, 354);
			int result = anotherPreparedStatement.executeUpdate();
			System.out.println(result);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Vamos praticar orientação a objetos?

Tempos atrás li o livro Essays on Software Technology and Innovation da série Pragmatic Programmers. Gostei bastante do livro e vou hoje resumir um dos capítulos que considero uma ótima referência para escrever um código utilizando orientação a objetos. O capítulo foi escrito por Jeff Bay com o título Object Calisthenics.

Em termos gerais, apesar de termos diversos recursos de linguagens orientadas a objetos, ainda hoje escrevemos códigos extensos, difíceis de testar e repetitivos.
Para melhorar nossos códigos, Jeff Bay propõe um exercício no qual você deve escrever 1000 linhas de código, seguindo rigorosamente as 9 regras descritas abaixo. Acredite, este exercício pode transformar a maneira como você escreve seu código:

1) Um nível de identação por método
Se uma classe com mais de 500 linhas já assusta a primeira vista, o que dizer de um método? Uma boa referência para manter seu código compreensível é ter por volta de 5 linhas por método. Isto pode ser assustador, mas caso não seja possível, garanta que um método faça apenas uma única coisa. Para isso, não escreva métodos com mais de um nível de identação, como neste exemplo:

class Board {
	...
	String board() {
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) 
				buf.append(data[i][j]);
			buf.append(“\n”);
		} 
		return buf.toString();
	}
}

Após aplicação da regra ficaria:

	String board() {
		StringBuffer buf = new StringBuffer();
		collectRows(buf);
		return buf.toString();
	}

	void collectRows(StringBuffer buf) {
		for (int i = 0; i < 10; i++)
			collectRow(buf, i);
	}

	void collectRow(StringBuffer buf, int row) {
		for (int i = 0; i < 10; i++) 
			buf.append(data[row][i]);
		buf.append(“\n”);
	}

2) Não use o comando ELSE
O comando IF/ELSE é simples para entender, porém, não é difícil encontrar uma sequência de IF/ELSE tão extensa, que é quase impossível de ser compreendida, o mesmo vale para o comando CASE.
Nas linguagens orientadas a objetos é possível reduzir o uso de IFs com polimorfismo, patterns como o Null Object, ou ainda em linguagens como Java, com Enums ou com auxílio da API Reflection.
Então a segunda regra do exercício é esta: não use o comando ELSE. Use a criatividade para pensar em outras soluções para esta restrição.

3) Use objetos para primitivos e Strings
A linguagem Java é orientada a objetos, então não faz sentido usar uma regra diferente para declarar tipos, no caso usar primitivos. A definição da classe, além disso, proporciona informações adicionais tanto para o compilador como para o desenvolvedor, não permitindo por exemplo passar uma variável Ano, para um método que espera receber uma variável Hora. Criar pequenos objetos como Hora, Nome ou CPF, permite também adicionar validações nos lugares corretos, evitando os famosos Utils.validaIsso() ou Utils.validaAquilo().

4) Use uma coleção por classe
A regra número 4 é simples: se a classe tiver alguma variável que seja uma coleção, esta não deve ter nenhuma outra variável de classe. Toda coleção é encapsulada em sua própria classe. Esta regra, em Java, pode parecer ter sentido apenas quando não existia o conceito de Generics, que garante que a coleção só terá os tipos definidos pelos métodos utilizados para adicionar ou remover um elemento. Porém, esta regra garante também que os códigos relacionados a manipulação ou iteração com a coleção, estarão nos lugares apropriados e não espalhados no meio de outras classes.

5) Um ponto por linha
Esta regra é a aplicação da lei de Demeter, que determina que uma unidade deve interagir apenas com quem conhece, ou com quem está próximo. Violar esta regra indica que a sua unidade de código não está com o encapsulamento adequado, além de criar acoplamentos desnecessários. Veja o exemplo abaixo:

class Board {
 ...
 class Piece {
 ...
 	String representation;
 }
 
 class Location {
 ...
 	Piece current;
 }
 
 String boardRepresentation() {
	 StringBuffer buf = new StringBuffer();
	 for (Location l : squares()) 
	 	buf.append(l.current.representation.substring(0, 1));
	 return buf.toString();
 }
 
}

O código refatorado ficaria assim:

class Board {
 ...
 class Piece {
	 ...
	 private String representation;
	 
	 String character() {
	 	return representation.substring(0, 1);
	 }
	 	
	 void addTo(StringBuffer buf) {
		 buf.append(character());
	 }
 }
 
 class Location {
	 ...
	 private Piece current;

	 void addTo(StringBuffer buf) {
	 	current.addTo(buf);
	 }
 }
 
 String boardRepresentation() {
	 StringBuffer buf = new StringBuffer();
	 for (Location l : squares()) 
		 l.addTo(buf);
	 return buf.toString();
 }
}

6) Não abrevie
Abreviações fazem muito sentido apenas para quem as criou. Variáveis, métodos ou classe com nomes abreviados confundem. Se é necessário abreviar para reduzir a quantidade de caracteres digitados, talvez o código esteja sendo utilizado para fazer muitas coisas, o que quebra o princípio de coesão. Nomes muito longos também são um indicativo de que o código pode ser melhorado e que o método pode estar com mais responsabilidades do que deveria ter.
Nesta regra, utilize nomes com 1 ou 2 palavras, que representem fielmente o que o código faz. Evite também duplicar nomes para representar um contexto: Em uma classe com o nome Order, não é necessário ter um método com o nome Order.shipOrder(), basta chamar de Order.ship(), que é claro e representa bem o que será feito.

7) Mantenha todas as entidades pequenas
Esta regra restringe qualquer classe com mais de 50 linhas e qualquer pacote com mais de 10 classes. Uma classe extensa é um forte indício de que ela faz mais do que deveria fazer e suas responsabilidades poderiam ser quebradas em classes menores. Manter um pacote com poucas classes faz com que as classes neste pacote tenham forte relação, criando uma identidade para o pacote. Isto ajuda a manter unidades coesas, um contexto apropriado e responsabilidades únicas.

8) Nenhuma classe com mais de duas variáveis de instância
A ideia desta regra é fortalecer código coeso. Classes com mais de duas variáveis de instância terão responsabilidades além do necessário, além disso, quanto mais estado, mais riscos para problemas de concorrência. Veja o exemplo abaixo:

class Name {
 String first;
 String middle;
 String last;
}

Ficaria assim:

class Name {
 Surname family;
 GivenNames given;
}
class Surname {
 String family;
}
class GivenNames {
 List<String> names;
}

9) Sem getters/setters/propriedades
Esta regra reforça a coesão, assim como a regra anterior. A ideia é manter comportamento e estados em lugares apropriados, mantendo assim objetos modulares, simples e fáceis de serem compreendidos. Objetos coesos também evitam código duplicado, uma vez que é mais fácil reaproveitar métodos e classes que tem responsabilidades únicas.

Conclusão
A aplicação dessas regras é nada mais nada menos que a aplicação da programação orientada a objetos. Aplicar as regras, lhe força a pensar em código modular e encapsulado, o que facilita o reaproveitamento e mantém o desacoplamento entre as classes. Pense em um jogo de Lego: qual peça é mais fácil encaixar com as outras? Quanto menor a peça, mais fácil de encaixar, maior o reaproveitamento e mais fácil é substituí-la.

Faça o teste: escreva 1000 linhas de código aplicando essas regras e conte um pouco como foi o resultado!

Como criar um repositório de imagens usando Java e o Amazon S3

Olá! Até tempos atrás, quando Cloud Computing não tinha as proporções que vemos hoje, era comum salvar imagens e outros arquivos estáticos em um diretório no servidor ou em banco de  dados em campos do tipo BLOB.

Hoje é possível salvar imagens e arquivos estáticos em serviços na nuvem, como o Amazon S3.

Para fazer isto em Java, você precisar ter uma conta na Amazon AWS, criar um Bucket no S3 e colocar o AWS SDK Java no seu classpath.

Para salvar no S3, você precisa criar um objeto do tipo AWSCredentials, para fazer a autenticação no serviço e então instanciar um objeto do tipo AmazonS3

String accessKey = &quot;accessKey&quot;;
String secretKey = &quot;secretKey;
AWSCredentials awsCredential = new BasicAWSCredentials(accessKey, secretKey);
AmazonS3 s3 = new AmazonS3Client(awsCredential);

Agora que temos o objeto AmazonS3, vamos buscar o conteúdo do arquivo, o InputStream, e também criar um objeto do tipo ObjectMetaData, que representa um objeto armazenado no S3. Para criar o objeeto do tipo ObjectMetaData é preciso informar o tamanho do arquivo em bytes:

InputStream inputStream = new FileInputStream(&quot;img/image.jpg&quot;);
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(inputStream.available());

Tendo o objeto ObjectMetadata criado, agora é necessário chamar o método que de fato publica o arquivo no S3. Para isso, é preciso informar o nome do bucket, o nome do arquivo no S3, o inputStream do arquivo, e o objeto ObjectMetadata:

String bucketName = &quot;bucketName&quot;;
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, &quot;image.jpg&quot;, inputStream, objectMetadata);
s3.putObject(putObjectRequest);

Agora que o arquivo foi publicado no S3, você pode acessá-lo pela URL abaixo:

<pre>https://s3-sa-east-1.amazonaws.com/bucketName/image.jpg</pre&gt;

Abaixo o snippet completo:

public class S3Snippet {

	public static void main(String[] args) {
		String accessKey = &quot;accessKey&quot;;
		String secretKey = &quot;secretKey&quot;;
		AWSCredentials awsCredential = new BasicAWSCredentials(accessKey, secretKey);
		AmazonS3 s3 = new AmazonS3Client(awsCredential);

		try {
			InputStream inputStream = new FileInputStream(&quot;img/image.jpg&quot;);
			ObjectMetadata objectMetadata = new ObjectMetadata();
			objectMetadata.setContentLength(inputStream.available());

			String bucketName = &quot;bucketName&quot;;
			PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, &quot;image.jpg&quot;, inputStream, objectMetadata);
			s3.putObject(putObjectRequest);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

Black Bird

Olá!

O blog Black Bird foi criado para compartilhar coisas maneiras sobre desenvolvimento e programação. É mantido por Alisson Medeiros e Marcos Roberto Ferreira, dois amigos que resolveram contar histórias e trocar alguns snippets de código.

O nome Black Bird foi adotado aleatoriamente em um evento de desenvolvedores. A premissa, segundo Marcos, um dos autores do blog, é que o nome fosse relacionado com a palavra “Black”, originária do seu apelido de infância: Negão. Alisson então, outro autor do blog, com sua perspicácia, sugeriu que o nome fosse Black Bird, em menção ao supersônico Lockheed SR-71 Blackbird, que foi projetado para ser imperceptível aos radares.

Black Bird também é o nome de uma música dos Beatles, que possuí algumas interpretações relacionadas a espiritualidade, liberdade e a busca pela essência daquilo que se acredita.