Tomcat 8 rodando como serviço

#adicionar o script do final do post com o nome tomcat em /etc/init.d/

sudo vim /etc/init.d/tomcat

#tornar arquivo executável

sudo chmod +x /etc/init.d/tomcat

#adicionar script ao chkconfig

sudo chkconfig --add /etc/init.d/tomcat

#habilitar o serviço no startup EC2

sudo chkconfig tomcat on

#Ubuntu

sudo update-rc.d tomcat defaults

Arquivo: tomcat

#!/bin/bash
#
# tomcat8 This shell script takes care of starting and stopping Tomcat
# Description: This shell script takes care of starting and stopping Tomcat
# chkconfig: - 80 20
#
## http://blog.maestropublishing.com/2013/04/23/tomcat7-service-startstop-script/
## Source function library.
. /etc/init.d/functions

TOMCAT_HOME=/home/ec2-user/tomcat
SHUTDOWN_WAIT=30

tomcat_pid() {
  echo `ps aux | grep org.apache.catalina.startup.Bootstrap | grep -v grep | awk '{ print $2 }'`
}

start() {
  pid=$(tomcat_pid)
  if [ -n "$pid" ]
  then
    echo "Tomcat is already running (pid: $pid)"
  else
    # Start tomcat
    echo "Starting tomcat"
    /bin/bash $TOMCAT_HOME/bin/startup.sh
  fi
  return 0
}

stop() {
  pid=$(tomcat_pid)
  if [ -n "$pid" ]
  then
    echo "Stopping Tomcat"
    /bin/bash $TOMCAT_HOME/bin/shutdown.sh

    let kwait=$SHUTDOWN_WAIT
    count=0;
    until [ `ps -p $pid | grep -c $pid` = '0' ] || [ $count -gt $kwait ]
    do
      echo -n -e "\nwaiting for processes to exit";
      sleep 1
      let count=$count+1;
    done

  if [ $count -gt $kwait ]
  then
    echo -n -e "\nkilling processes which didn't stop after $SHUTDOWN_WAIT seconds"
    kill -9 $pid
  fi
  else
    echo "Tomcat is not running"
  fi
  return 0
}

case $1 in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    stop
    start
    ;;
  status)
    pid=$(tomcat_pid)
    if [ -n "$pid" ]
      then
      echo "Tomcat is running with pid: $pid"
      else
      echo "Tomcat is not running"
    fi
    ;;
esac
exit 0

Instalar java Oracle a partir de um RPM

Para instalar o JDK da oracle a partir de um pacote RPM execute os seguintes comandos abaixo no terminal:

1 – Download da versão escolhida, neste caso 8u25

wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u31-b13/jdk-8u31-linux-x64.rpm

2 – Instalar o java

sudo rpm -ivh jdk-8u31-linux-x64.rpm

3 – Adicionar nas alternativas do sistema operacional

sudo /usr/sbin/alternatives --install /usr/bin/java java /usr/java/jdk1.8.0_31/bin/java 100

4 – Configurar o java default

sudo /usr/sbin/alternatives --config java

5 – Conferir se está apontando para o java correto

java -version

Para remover execute os seguintes comandos:

1 – Remover das alternativas do sistema operacional

sudo /usr/sbin/alternatives --remove java /usr/java/jdk1.8.0_25/bin/java

2 – Executar uma query no gerenciador de pacotes para identificar o nome do pacote a ser excluído

rpm -qa | grep jdk

3 – Remover o pacote instalado

sudo rpm -e jdk1.8.0_25-1.8.0_25-fcs.x86_64

4 – Apagar o pacote baixado

rm jdk-8u25-linux-x64.rpm

Migração Trac e Subversion para Dreamhost

Tutorial para migração de subversion e trac 0.12 para dreamhost

Na informática temos várias maneiras de executar a mesma tarefa e o tutorial abaixo descreve os procedimentos que melhor se adaptaram ao caso prático e aos conhecimentos do autor.

Obs:. Os comandos devem ser ajustados a realidade dos seus servidores

Migrando Subversion

Crie um novo subdomínio e um repositório seguindo os três passos (na verdade o segundo passo é apenas aguardar a propagação de DNS) conforme instruções oficiais da Dreamhost.

Observe que após criar o novo subdomínio será adicionado um novo diretório com o caminho similar a este: /home/username/svn.yourhost.com
E após criar o novo repositório será criado um diretório “svn” em sua home para guardar o projeto versionado e os arquivos contendo as senhas e permissões de acesso.

Neste momento você já pode testar seu repositório através do browser acessando um endereço similar a este http://svn.yourhost.com/yourproject
(Pode demorar alguns minutos para o servidor criar o novo subdomínio e/ou o novo repositório)

Se você conseguiu acessar o repositório na Revision 0 continuaremos com o backup e restore do projeto!

#Backup do repositório atual
svnadmin dump /var/www/svn/yourproject/ | gzip > svn_yourproject.gz

#Enviando o backup para o novo servidor
scp svn_yourproject.gz username@yourhost.com:~

#Restaurando o backup no novo servidor
gunzip -c svn_yourproject.gz | svnadmin load svn/yourproject

Teste novamente o acesso on-line e verá o repositório do subversion trabalhando com seu último commit.

Fonte: http://wiki.dreamhost.com/Subversion#Loading_a_dumpfile

Migrando Trac

Agora vem a parte interessante! Se o Trac anterior estivesse na mesma versão do Trac da dreamhost seria tudo mais simples e não precisariamos criar um novo ambiente python para instalar o trac manualmente pois a dreamhost disponibilizado tudo pelo painel conforme consta aqui http://wiki.dreamhost.com/Trac ou se o repositório não estivesse sendo migrado! Mas o meu problema é que a versão atual do Trac é 0.12 e a dreamhost está trabalhando com a versão 0.11.X, então vamos lá.

Criando um Ambiente Virtual Python

Estamos trabalhando com uma conta normal na Dreamhost, ou seja, não temos uma VPN e nenhum privilégio para instalar programas ou alterar o servidor a vontade. Então para instalarmos a versão 0.12 do Trac que roda em python iremos criar um “ambiente virtual python”.

#Baixar o pacote do site oficial
wget https://raw.github.com/pypa/virtualenv/master/virtualenv.py

#Criar o ambiente virtual
python virtualenv.py python

#Instalação de pacote pre-requisito para o Trac
python/bin/python python/bin/easy_install Genshi

#Instalar o Trac na versão 0.12
python/bin/python python/bin/easy_install Trac==0.12

Agora, através do painel da dreamhost crie o subdomínio trac.yourhost.com

#Criar diretório para o projeto Trac
mkdir trac.yourhost.com/yourproject

#Criando o ambiente Trac
python/bin/trac-admin trac.yourhost.com/yourproject/ initenv

#Criando um diretório para receber os arquivos CGI, conforme http://trac.edgewall.org/wiki/0.12/TracInstall#RunningTraconaWebServer
mkdir deploy

#Criando scripts e docs
python/bin/trac-admin trac.yourhost.com/yourproject/ deploy deploy

#Copiando scripts e docs para o ambiente do projeto
mv deploy/* trac.yourhost.com/yourproject

Proteger o diretório do ambiente Trac seguindo o passo 5 deste passo-a-passo.

Basicamente é só entrar em Goodies > Htaccess/WebDAV e seguir a orientação.

Adicione a configuração abaixo em seu .htaccess, lembre de dar permissão de escrita (chmod 644 .htaccess) e depois retirá-la (chmod 444 .htaccess)

SetHandler fastcgi-script

DirectoryIndex index.fcgi

# Make sure rewrites work
Options ExecCGI FollowSymLinks
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond $1 !^index.fcgi/(.*)
# Keep the graphics and style sheet the way they are
RewriteCond $1 !^htdocs(.*).css$
RewriteCond $1 !^htdocs(.*).js$
RewriteCond $1 !^htdocs(.*).gif$
RewriteCond $1 !^htdocs(.*).jpg$
RewriteCond $1 !^htdocs(.*).png$
RewriteRule ^(.*)$ index.fcgi/$1 [L]

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} attachment
RewriteCond $1 !^index.fcgi/(.*)
RewriteRule ^(.*)$ index.fcgi/$1 [L]

Finalmente crie um arquivo executável index.fcgi com seu editor de textos preferido, conforme exemplo abaixo:

cd trac.yourhost.com/yourproject
vim index.fcgi
Adicione o texto abaixo no script (ajustando para seu ambiente)
#!/bin/bash
export TRAC_ENV=”/home/username/trac.yourhost.com/yourproject/”
exec /home/username/trac.yourhost.com/yourproject/cgi-bin/trac.fcgi

#Torne o arquivo executável
chmod +x index.fcgi

Neste momento você já deve ter o Trac 0.12 instalado e rodando no ambiente virtual python, teste no browser: http://trac.yourhost.com/yourproject

Agora iremos migrar os dados do Trac:

Acesse o servidor antigo
#Backup do banco de dados do Trac
sudo /usr/bin/sqlite3 /home/username/trac/projects/yourproject/db/trac.db “.dump” >> trac_yourproject_sqlite.sql

Caso o caminho do novo repositório no servidor novo seja diferente do caminho atual depois de executado o backup do banco de dados é necessário alterar o arquivo manualmente informando o Caminho do repositório subversion instalado no novo servidor pois quando o arquivo for restaurado o trac já reconhecerá o caminho.

Abra o arquivo com seu editor de textos favorito e procure uma linha similar a linha abaixo:

INSERT INTO “repository” VALUES(1, ‘repository_dir’, ‘svn:c07cc470-69bf-4681-9e92-510e6bfb17be:/var/www/svn/yourproject’);
#Substitua o caminho antigo pelo novo, exemplo
INSERT INTO “repository” VALUES(1, ‘repository_dir’, ‘svn:c07cc470-69bf-4681-9e92-510e6bfb17be:/home/username/svn/yourproject’);

#Enviando o backup para o novo servidor
scp trac_yourproject_sqlite.sql username@yourhost.com:~

Acesse o servidor da dreamhost via SSH

#Restaurando o backup do banco de dados
cat trac_yourproject_sqlite.sql | sqlite3 trac.db

#Movendo o backup para o diretório correto (é interessante fazer um backup do banco atual)
mv trac.db trac.yourhost.com/yourproject/db/trac.db

#Acesse o arquivo de configuração do Trac e no parâmetro repository_dir informe o path do repositório
vim trac.yourhost.com/yourproject/conf/trac.ini

#A linha ficará semelhante a informação abaixo
repository_dir = /home/username/svn/yourproject

Neste momento o meu Trac passou a informar o seguinte Erro:
Warning: Can’t synchronize with repository “(default)” (Unsupported version control system “svn”: No module named svn). Look in the Trac log for more information

Como estamos utilizando um ambiente python virtual diferente do que existe no servidor as configurações do python bindings e os módulos configurados ficaram inacessíveis.

A maneira mais simples de corrigir isto é criar um link simbólico fazendo com que o ambiente virtual utilize a configuração já existente no servidor da dreamhost.

ln -s /usr/lib/pymodules/python2.6/svn python/lib/python2.6/site-packages/svn
ln -s /usr/lib/pymodules/python2.6/libsvn python/lib/python2.6/site-packages/libsvn

Obs.: Aqui no meu browser ficou uma espécie de cache que precisei rodar CTRL + F5 muitas vezes para o erro sumir.

#Migrando os anexos existentes
scp -r attachments/* username@yourhost.com:/home/username/trac.yourhost.com/yourproject/attachments

Fonte: http://trac.edgewall.org/wiki/TracMigrate#TracMigration

#Configurar envio de e-mails e logomarca em trac.ini

[header_logo]
alt = Your Enterprise

src = http://www.yourhost.com/logo.png

[notification]
email_sender = SendmailEmailSender
mime_encoding = base64
sendmail_path = /usr/sbin/sendmail
smtp_always_cc = username@youhost.com
smtp_enabled = true
smtp_from = trac@yourhost.com
smtp_replyto = trac@yourhost.com

Configurando SSL no Tomcat

Este tutorial em como objetivo mostrar como configurar SSL (acesso https://localhost:8443) no Tomcat.

A configuração consiste em 4 passos básicos:

1 – Criar um arquivo keystore usando Java
2 – Configurar o Tomcat para usar o keystore
3 – Testar
4 – Configurar sua web app para usar SSL (acesso através https://localhost:8443/suaApp)

1 – Criando um arquivo keystore usando Java

Abra o terminal do seu computador e digite:

Linux:

$ cd /usr/local/java/bin

Mac

$ cd /Library/Java/Home/bin

Você irá mudar o diretório corrente para o diretório de instalação Java para a pasta bin. Dentro da pasta bin existe um arquivo chamado keytool. Esse arquivo é responsável por gerar o arquivo keystore.

Vamos agora gerar o keystore. Digite no terminal:

keytool -genkey -alias tomcat -keyalg RSA

Quando der “Enter” no comando acima, irá aparecer algumas perguntas. Primeiro irá pedir para criar uma senha (escolhi “password” mesmo):

loiane:bin loiane$ keytool -genkey -alias tomcat -keyalg RSA

Enter keystore password:  password
Re-enter new password: password
What is your first and last name?
[Unknown]:  Loiane Groner
What is the name of your organizational unit?
[Unknown]:  home
What is the name of your organization?
[Unknown]:  home
What is the name of your City or Locality?
[Unknown]:  Sao Paulo
What is the name of your State or Province?
[Unknown]:  SP
What is the two-letter country code for this unit?
[Unknown]:  BR
Is CN=Loiane Groner, OU=home, O=home, L=Sao Paulo, ST=SP, C=BR correct?
[no]: yes
Enter key password for
(RETURN if same as keystore password):  password
Re-enter new password: password

O arquivo .keystore será criado no seu diretório home. No WIndows será algo do tipo C:\Documents and Settings\<username>; no Mac será /Users/<username> e no Linux será /home/<username>.

2 – Configurando o Tomcat para usar o keystore

Abra o diretório de instalação do Tomcat e abra a pasta conf . Dentro dessa pasta irá encontrar um arquivo chamado server.xml. Vamos editar esse arquivo.

Ache a seguinte declaração:

<!--

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
-->

Descomente o código acima e altere para ficar como abaixo – detalhe para o diretório onde está o keystore e a senha que setou quando criou o keystore:

<Connector SSLEnabled="true" acceptCount="100" clientAuth="false"

disableUploadTimeout="true" enableLookups="false" maxThreads="25"
port="8443" keystoreFile="/Users/loiane/.keystore" keystorePass="password"
protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https"
secure="true" sslProtocol="TLS" />

3 – Vamos testar!

Inicie o serviço do Tomcar e tente acessar https://localhost:8443. Deverá abrir a homepage local do Tomcat.

Note também que se tentar acessar pela porta padrão 8080 deverá funcionar também:http://localhost:8080

4 – Configurando sua web app para usar SSL (acesso através https://localhost:8443/suaApp)

Para forçar sua aplicação web a funcionar com SSL, adicione o código abaixo no arquivo web.xml da sua aplicação (antes do final da tag web-app):

<security-constraint>

<web-resource-collection>
<web-resource-name>securedapp</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>

A tag url pattern tem o valor /* para que qualquer página ou arquivo da sua aplicação seja seguro (só poderá ser acessado através de https). A tag transport-guarantee foi setado como CONFIDENTIAL para fazer com que a aplicação seja acessada através de SSL.

Se desejar desativar o acesso SSL da aplicação, não precisa deletar o código do arquivo web.xml, basta trocar oCONFIDENTIAL para NONE.

Referência: http://www.loiane.com/2011/06/configurando-ssl-no-tomcat-em-5-minutos-httpslocalhost8443/

 

Auto-completar com o Plugin JQuery para Struts 2

Neste tutorial iremos aprender como fazer um campo auto-completar utilizando o plugin JQuery para Struts 2. Como exemplo utilizaremos um campo de produtos.

1 – Baixar o plugin struts2-jquery-plugin-x.x.x.jar

http://code.google.com/p/struts2-jquery/downloads/detail?name=struts2-jquery-plugin-3.1.0.jar

2 – Copiar o plugin struts2-jquery-plugin-x.x.x.jar para a pasta libraries/struts2.x.x

3 – Adicionar o plugin as bibliotecas do projeto;

4 – Criar a seguinte classe:

package com.tartigrado.strada.model;
public class ProductList {

    private Long id;
    private String description;

    public ProductList(Long id, String description) {
        this.id = id;
        this.description = description;
    }

    //GET - SET

5 – Criar o seguinte método na classe ProductDAO:


@Transactional(readOnly=true)
public List<ProductList> findByDescription(String description) {
   description = "%" + description + "%";
   StringBuilder command = new StringBuilder();
   command.append("select new com.tartigrado.strada.model.ProductList(id, description) from Product ");
   command.append("where description LIKE :description ");
   command.append("order by description");
   Query query = this.em.createQuery(command.toString());
   query.setParameter("description", description);
   query.setMaxResults(10);
   return query.getResultList();
}

6 – Disponibilizar o método  “List<Product> findByDescription(String description)” na interface e implementação do produto;

7 – Criar no arquivo product-struts.xml a seguinte declaração de Action:

<package name="productJSON" extends="json-default">
    <action name="findProductJSON" class="com.tartigrado.strada.controller.ProductAction" method="findProductJSON">
        <result name="success" type="json" />
    </action>
</package>

8 – Criar o atributo term do tipo String na Classe ProductAction.java para receber o texto que foi digitado no campo auto-completar;

9 – Criar o seguinte método na Classe ProductAction.java:

public String findProductJSON() {
    setProductsList(service.findByDescription(getTerm()));
    return SUCCESS;
}

OBS: Verificar o método prepare para que nenhum código gere erro ao chamar o método findProduct JSON()

10 – Criar na classe responsável pela JSP onde vai estar o campo auto-complete (Ex: BuyAction.java) o atributo Long idProduct para receber o valor que vem da JSP;

11 – Não existindo o seguinte trecho de código no arquivo header.jspf inseri-lo:

<%@ taglib prefix="sj" uri="/struts-jquery-tags"%>

<sj:head jqueryui="true" jquerytheme="cupertino"/>

12 – Criar o seguinte trecho de código JavaScript na página JSP onde se encontra o campo auto-completar:

<script type="text/javascript">
    $.subscribe("autocompleteSelectProduct", function(event, data) {
        var productSelected = event.originalEvent.ui.item;
        $("#idProduct").val(productSelected.value);
        var nameProduct = productSelected.label;
        nameProduct = nameProduct.replace(/<strong>/g,'').replace(/<\/strong>/g,'');
        $("#nameProduct").val(nameProduct);
    });

    $.subscribe("clearFieldProduct", function(event, data) {
        var nameProduct = document.getElementById('nameProduct').value;
        if (nameProduct != '') {
            $("#product").val("");
            $("#product").val(document.getElementById('nameProduct').value);
            $("#nameProduct").val("");
        }
    });

    $.subscribe("addAtributeProduct", function(event, data) {
            var options = {};
            options.delay = 50;
            options.minimum = 2;
            options.selectBox = false;
            options.onsearchtopics = "addAtributeProduct";
            options.onselecttopics = "autocompleteSelectProduct";
            options.list = "productsList";
            options.listkey = "id";
            options.listvalue = "description";

            options.jqueryaction = "autocompleter";
            options.id = "product";
            options.oncom = "clearFieldProduct";
            options.href = "findProductJSON.action";

            jQuery.struts2_jquery.bind($('#product'), options);
    });
</script>

13 – Inserir o seguinte código no formulário onde se encontra o campo auto-completar:

Produto: <sj:autocompleter name="product" id="product" size="20" onSearchTopics="addAtributeProduct"/>
<s:hidden name="idProduct" id = "idProduct" />
s:hidden name="nameProduct" id = "nameProduct" />