Avri Blog

Blog à l'avricot - Lord Of Castle, java, nosql, Utomia, AvriChat, javascript, Json, Css, Mootools, ajax, php...

Aller au contenu | Aller au menu | Aller à la recherche

Stop Bubble | Start

dimanche, janvier 16 2011

Eclipse .classpath bug with mvn eclipse:eclipse and wtp tomcat server, lib not deployed

I recently had an issue with eclipse wtp server configuration.
My libs wasn't deployed, and the context wasn't corretly loaded.
(I used maven eclipse plugin to generate my configuration files :

  • eclipse:configure-workspace => add the classpath variable M2_REPO to Eclipse which points to your local repository and optional to configure other workspace features.
  • eclipse:eclipse => generates the Eclipse configuration files.

The solution was to manually update my .classpath file, which was wrong.

Here is a correct version of the file, ready for a very "classic" web app !

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
	<classpathentry kind="src" output="target/classes" path="src/main/resources"/>
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER">
		<attributes>
			<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
	<classpathentry kind="output" path="target/classes"/>
</classpath>

Setting property 'source' to 'org.eclipse.jst.jee.server:xxx' did not find a matching property.

If you are facing the following error :

Setting property 'source' to 'org.eclipse.jst.jee.server:xxx' did not find a matching property.

The solution to this problem is very simple:
Open your tomcat server. In the "Server Options" part, check "Publish module contexts to separate XML files.
Restart, Done ;)

vendredi, janvier 14 2011

find a file in many jars

A quick bash to find a file in a list of jars :

#!/bin/bash
echo 'find for ' $1
for i in *.jar ; do
        echo $i 
        jar tvf $i | grep --color "$1"
done

samedi, décembre 25 2010

monitoring web site using python

Last week, I had to monitor one of our website, to make sure N div was correctly displayed on the page.
I had to be alerted everytime the number of div changed on the page.
I made a little script based on this one Basically, it stores the data using a pickle file, and send an email every time the number of the specific div changes on the page.

#!/usr/bin/env python
 
# sample usage: checksites.py yoursite.com othersite.org
 
import pickle, os, sys, logging
import string
import email.utils
from httplib import HTTPConnection, socket
from smtplib import SMTP
from email.mime.text import MIMEText
 
 
PROXY = ''
 
 #===== Headers =================================================================
 
 #    'Accept' : 'text/plain, text/html',
 
 
headers_get = {
    'Accept-Encoding'    : 'gzip, deflate',
    'Accept'             : '*/*',
    'Accept-Language'    : 'en-au',
    'Connection'         : 'Keep-Alive',
    'User-Agent'         : 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727'
 }
 
headers_post = {
    'Content-type'       : 'application/x-www-form-urlencoded',
    'Accept'             : 'text/plain'
 }
 
 
def email_alert(url, status):
    print("sending email...")
    fromaddr = 'from@mail.com'
    toaddrs = 'to@mail.com'
 
    server = SMTP('smtp@mail.com')
    msg = MIMEText('alert for %s : \r\n %s'  % (url, status) )
    msg['To'] = email.utils.formataddr(('Recipient', toaddrs))
    msg['From'] = email.utils.formataddr(('Author', fromaddr))
    msg['Subject'] = 'CHANGEMENT CACHE ADSERVER: '+status
 
    #server.starttls()
    #server.login('you', 'password')
    server.sendmail(fromaddr, [toaddrs], msg.as_string())
    #server.quit()
    server.close()
    print("email sent")
 
#count the number of "boite"
def count_boite_element (data):
    return string.count(data,'<div class="element_boite">')
 
#get status (up or down)
def get_site_status(response):
    status = 000
    try:
        status = getattr(response, 'status') 
        if status == 200 or status == 302:
            return 'up (%d)' % (status)
    except AttributeError:
        pass
    print(response)
    return 'down (%d)' % (status)
 
#get the HTTPConnect response object from url
def get_response(url):
    '''Return response object from URL'''
    if (url.find('/')>=0):
        print(url)
        base_url = url[0:url.find('/')]
        path = url[len(base_url):]
    else:
		base_url = url
		path = ""
    print("init conn sur "+base_url+" => "+path)
    try:
        conn = HTTPConnection(base_url)
        conn.request('GET', path, None, headers_get)
        print("conn done")
        return conn.getresponse()
    except socket.error:
        return None
    except:
        logging.error('Bad URL:', url)
        exit(1)
 
def get_headers(url):
    '''Gets all headers from URL request and returns'''
    response = get_response(url)
    try:
        return getattr(response, 'getheaders')()
    except AttributeError:
        return 'Headers unavailable'
 
def compare_site_status(prev_results):
    '''Report changed status based on previous results'''
 
    def is_status_changed(url):
        response = get_response(url)
        status = get_site_status(response)
        if status.find('down')<0:
	        data = response.read()
	        boite_nb = count_boite_element(data)
        else:
			boite_nb = 0
        friendly_status = '%s is %s with %s boite element' % (url, status, boite_nb)
        print friendly_status
        print(prev_results)
        if (url in prev_results) and ((prev_results[url]['status'] != status) or ( prev_results[url]['boite_nb'] != boite_nb)) :
            logging.warning(friendly_status)
            # Email status messages
            email_alert(url, friendly_status)
        prev_results[url] = {'status' : status, 'boite_nb' : boite_nb}
 
    return is_status_changed
 
def is_internet_reachable():
    '''Checks Google then Yahoo just in case one is down'''
    if get_site_status(get_response('www.google.com')).find('down')>=0 and get_site_status(get_response('www.yahoo.com')).find('down')>=0 :
        return False
    return True
 
def load_old_results(file_path):
    '''Attempts to load most recent results'''
    pickledata = {}
    if os.path.isfile(file_path):
        picklefile = open(file_path, 'rb')
        pickledata = pickle.load(picklefile)
        picklefile.close()
    return pickledata
 
def store_results(file_path, data):
    '''Pickles results to compare on next run'''
    output = open(file_path, 'wb')
    pickle.dump(data, output)
    output.close()
 
def main(urls):
    # Setup logging to store time
    logging.basicConfig(level=logging.WARNING, filename='checksites.log',
            format='%(asctime)s %(levelname)s: %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S')
 
    # Load previous data
    pickle_file = 'data.pkl'
    pickledata = load_old_results(pickle_file)
 
    # Check sites only if Internet is_available
    if is_internet_reachable():
        status_checker = compare_site_status(pickledata)
        map(status_checker, urls)
    else:
        logging.error('Either the world ended or we are not connected to the net.')
 
    # Store results in pickle file
    store_results(pickle_file, pickledata)
 
if __name__ == '__main__':
    # First arg is script name, skip it
    main(sys.argv[1:])

lundi, mai 17 2010

driver XA et non-XA, 2 phase commit (2PC)/1PC et JTA

En travaillant avec Websphere Application Serveur et plus particulierement commerce, je me suis retrouvé face à cette erreur :

RegisteredRes E WTRN0063E: An illegal attempt to enlist a one phase capable resource with existing two phase capable resources has occurred" when attempting to execute a transaction.
... stack de l'erreur
Plus précisément :
"An attempt was made to have a one-phase resource participate in a global transaction while an XA resource or another one-phase resource already participated in this global transaction."

Le problème venait du fait que l'on se trouvait au sein d'une transaction globale (XA). En fait XA est la spécification qui décrit l'interface entre le Transaction Manager du serveur d'application et les les manager locaux des ressources pour pouvoir utiliser JTA (java transaction api).
Concrètement cela permet d'accéder à plusieurs ressources au sein d'une même transaction.
Dans notre cas, les multiples transactions sont faites à cause des transactions des EJB. Vu que c'est le container qui doit gérer automatiquement les transaction des ejb, d'autres appels sont fait (et donc des transactions créés) vers d'autres ressources lors de l'execution de la commande RMS. Il faut en fait voir un EJB comme une nouvelle ressource.
L'appel que je faisais à ma datasource extérieur créait une nouvelle transaction.
Dans un contexte normal, cette transaction isolée devrait pouvoir s'executer en tant que non-XA et donc en utilisant un 1PC. Pour raison obscure propre à la configuration de was (cela doit pouvoir être modifié, mais je n'ai pas trouvé comment), ce type d'action ne fonctionne pas de base. Une requête 1PC ne peut pas être utilisée dans un environnement
Du coup lorsque Transaction Manager fait un commit des transactions des EJB, il veut utiliser le protocole 2 phase commit pour valider l'envoie de toutes les transactions des ejb (celle qui lance une exception dans le tas).
Le driver de cette datasource n'étant pas de type XA, il n'implémentait pas le protocole 2PC et du coup on avait cette erreur.

La solution consistait donc à changer la classe du driver pour le passer en XA afin qu'il puisse faire ses 2PC !