Visualizzazione post con etichetta java. Mostra tutti i post
Visualizzazione post con etichetta java. Mostra tutti i post

giovedì 3 marzo 2011

JPanel con contorni a gradiente

Un pannello in Java dotato di bordi destro e sinistro con una sfumatura a gradiente di 10px.
Per un utilizzo corretto, occorre aggiungere un bordo "vuoto" di 10px affinchè il contenuto del pannello non si sovrapponga alla banda colorata:

pannelloConGradiente.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 10, 1, 10));

Per ottenere un bordo più o meno denso, basta parametrizzare lo spessore.

import javax.swing.JPanel;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

public class PanelWithBorder extends JPanel
{
 protected void paintComponent( Graphics g )
 {
  if ( !isOpaque( ) )
  {
   super.paintComponent( g );
   return;
  }

  Graphics2D g2d = (Graphics2D)g;
  int w = getWidth( );
  int h = getHeight( );

  Color color1 = getBackground( );
  Color color2 = color1.darker( );

  GradientPaint gpSxBorder = new GradientPaint(0, 0, color2, 10, 0, color1 );
  GradientPaint gpDxBorder = new GradientPaint(w-10, 0, color1, w, 0, color2 );

  g2d.setPaint( gpSxBorder);
  g2d.fillRect( 0, 0, 10, h );

  g2d.setPaint( gpDxBorder );
  g2d.fillRect( w-10, 0, w, h );

  setOpaque( false );
  super.paintComponent( g );
  setOpaque( true );
 }
}

sabato 27 febbraio 2010

Fonts per lavorare



Un font monospaced eccellente per sorgenti e terminali:

http://www.levien.com/type/myfonts/inconsolata.html

lunedì 17 marzo 2008

db4objects: un db engine object oriented

db4objects è un engine db object oriented con doppia licenza (alla MySQL) disponibile in versione open e in versione commerciale ed è in grado di integrarsi con Java e con la piattaforma .NET.
Sembra disporre di tutto ciò che serve (transazioni, query language avanzato, sistemi per il supporto al refactoring) per lo sviluppo di applicazioni orientate ai dati di nuova generazione.
Staremo a vedere.

giovedì 6 dicembre 2007

Metodologia OO2R

Ecco un modello pratico per la realizzazione di infrastrutture di persistenza per applicativi modellati su architetture Object Oriented. Il prodotto di questo modello non e' un vero e proprio DB Object Oriented, ma consente di sviluppare strati di persistenza consistenti per sistemi OO, sfruttando nel contempo quelli che sono i punti di forza (prestazionali) dei database relazionali.



Caratteristiche architetturali

Nello strato di persistenza non vengono implementati i metodi delle classi, ma soltanto gli attributi. Non sara' quindi possibile effettuare query con chiamate a metodi direttamente in SQL, ma sara' necessario passare dallo strato del linguaggio OO per questo tipo di query, con una penalizzazione delle prestazioni. Occorre quindi porre attenzione all'analisi architetturale del sistema, tenendo conto del trade-off tra design e performance.

Poiche' il sistema e' suddiviso in due strati (lo strato Java e lo strato DB) e' necessario sempre tenere presente quando e in che modo in due strati sono coinvolti nelle varie operazioni, per poter offrire una buona stima delle prestazioni del sistema in progetti reali dove queste siano essenziali.

Cerchero' sempre di sottolineare l'esatto livello di coinvolgimento dei due strati, con una digressione sulle performance.



Prerogative dei database OO

Elenco qui le golden rules dei database orientati agli oggetti: per quanto possibile cercherò di sviluppare un sistema che ricalchi queste regole, e quando non sarà possibile rispettarle, indicherò le motivazioni.

  • Oggetti complessi

Deve essere possibile creare oggetti complessi aggregando oggetti più semplici; inoltre deve essere possibile applicare i metodi di aggregazione ortogonalmente . Questa feature verrà implementata tramite una relazione di aggregazione.

  • Object identity

A differenza del modello relazionale in cui l'identità di una entità è relativa al valore dei suoi campi chiave, in un db object oriented è necessario identificare un oggetto indipendentemente dal suo valore; questa feature verrà implementa semplicemente inserendo come chiave di ogni tavola che rappresenta un oggetto un campo objectId (che in MySQL sarà un Integer con Auto-increment)

  • Incapsulazione

In questo caso, poichè i metodi degli oggetti non vengono implementati dal DB, ma dallo strato Java sovrastante, l'incapsulazione è implementata dall'oggetto “Java side”

  • Tipi e classi

Anche in questo caso ci baseremo sulle feature di Java. Solo lo strato di persistenza verrà delegato al DB, attraverso tavole rappresentanti le entità del sistema

  • Gerarchia di classi

Naturalmente la “Java side” del sistema implementa nativamente le gerarchie di classi. Da un punto di vista dello strato di persistenza, la relazione di ereditarietà verrà implementata utilizzando come chiave primaria e objectId della classe figlia, una foreign key puntante all'objectId della classe padre. Le interfaccie (che sono prive di attributi e quindi prive di stato di persistenza) verranno implementate come tavole il cui unico attributo è l'objectId. Questo per permettere il polimorfismo nelle query.



Componenti del sistema

Livello di database

Il database prevede due metaclassi di componenti:

  • Entità

  • Relazioni

Da un punto di vista OO le relazioni rimangono invariate rispetto al modello relazionale, mentre cambiano le entità: inoltre nasce un tipo di relazione di ereditarietà, che va quindi correttamente codificata in SQL.

Livello del linguaggio (Java)

Per ogni classe di oggetti persistenti sono necessari due componenti:

  • La classe stessa (che implementa DataObject)

  • Un gestore della persistenza specifico



La metodologia

Il punto di partenza di questa metodologia è il class diagram del sistema, che -ATTENZIONE! - dovrà essere nella “versione per l'implementazione in Java” piuttosto che nella “versione dell'architettura implementabile in qualunque linguaggio OO”. Questo perchè in Java tutti gli oggetti derivano da Object. Se questa feature viene in qualche modo sfruttata, anche nello strato di persistenza ci dovrà essere una tabella “Object” che offre foreign key a tutte le entità del sistema! Naturalmente questa implementazione potrebbe non essere accettabile (potrei avere un numero eccessivo di oggetti nel DB, tale da impattare troppo sulle prestazioni e sullo spazio utilizzato su disco). Inoltre lo strato di persistenza deve includere anche gli attributi privati e protetti dell'oggetto da serializzare (che normalmente nei diagrammi dell'architetto non compaiono).

Ad ogni classe persistente corrisponde una tabella di tipo Entità nel database. Inoltre ogni entità ha un objectId (regola della Object Identity dei DB ad oggetti) che è anche la chiave primaria della tavola.

Qualunque tipo di relazione (ereditarietà [is-a], composizione [has-a], oppure user defined [abita-presso], [ha-il-permesso-per], ecc) viene rappresentata da una relazione – sempre una tavola del DB – con eventuali attributi.

La relazione di ereditarietà viene espressa tramite una chiave esterna utilizzata anche come primary key nella classe specializzata.



Esempio pratico

Prendiamo un diagramma UML:


Per il momento tralasciamo i particolari implementativi, ci interessa principalmente la struttura.

Un DocumentoVendita è una classe astratta, implementata da Fattura e Bolla, che ne implementano il metodo astratto stampa().

Inoltre aggiungono ognuno un attributi specifico di questa classe. D'altra parte abbiamo un'interfaccia RigaDocumento, e due classi implementanti, RigaFattura e RigaBolla, ognuna con le sue caratteristiche specifiche (che tralasciamo). Un DocumentoVendita contiene (usa) una collezione di RigaDocumento (la relazione potrebbe essere has-many).

Vediamo come possiamo implementare in Java questo modello, e come possiamo realizzarne lo strato di persistenza su un DB relazionale:


La classe astratta DocumentoVendita viene implementata dalla tavola documento_vendita, che oltre ad enumerare tutti gli attributi (attenzione! sia pubblici che privati!) della classe aggiunge come PK objectId, e come attributo normale objectRTTI. Il primo è un numerico con auto-incremento, mentre il secondo contiene il nome della classe reale (foglia nell'albero della gerarchia) dell'oggetto polimorfo. Questo secondo attributo è necessario soltanto nelle classi base. Lo strato di persistenza delle classi che ereditano da documentoVendita, viene implementato attraverso tavole (una per ogni classe implementante, quindi bolla e fattura). Queste tavole contengono gli attributi specifici delle classi ereditate, oltre a objectId. Quest'ultimo però, oltre ad essere chiave primaria, è anche foreign key sull'omonimo campo della tavola della classe base (documento_vendita), e non è auto-increment. Di fatto lo stato persistente di un oggetto fattura è dato dal join naturale tra “bolla JOIN documento_vendita ON (bolla.objectId = documento_vendita.objectId)”.

[qui manca una bella disquisizione sulla relazione has_many]

Ora supponiamo di dover estendere il nostro sistema, aggiungendo un ulteriore livello di specializzazione nelle fatture:

In particolare abbiamo aggiunto la classe derivata FatturaPersonalizzata.

Vediamo come adattare lo schema del DB:

La query per il data retriving di una fattura personalizzata:

SELECT *

FROM fattura_personalizzata JOIN fattura JOIN documento_vendita

ON (fattura_personalizzata.objectId = fattura.objectId AND fattura.objectId = documento_vendita.objectId)

WHERE fattura_personalizzata.objectId = ?

E' importante notare che anche con una elevata profondità nel grafo della gerarchia, le ricerche per objectId hanno sempre un costo estremamente limitato!



lunedì 27 agosto 2007

Pool di risorse e gestione della memoria

Recentemente mi sono messo a meditare sulla gestione della memoria in Java: visto l’alto costo della new, pensavo di creare un generico contenitore template Pool in grado di contenere e riutilizzare risorse senza invocare la new; chiaramente gli oggetti avrebbero dovuto essere “abilitati” al riutilizzo attraverso un metodo di “rigenerazione” che facesse lo stesso lavoro di un’invocazione al distruttore + un’invocazione al costruttore senza coinvolgere il gestore della memoria della virtual machine (in C++ basterebbe sovraccaricare l’operatore di assegnamento). A questo punto avrei voluto implementare un qualche sistema per “sentire” l’uscita dallo scope di una reference all’oggetto per poter indicare al Pool quando segnare l’oggetto come inutilizzato e renderlo disponibile per essere riutilizzato. Non ci sono riuscito, e mi sono accontentato di un metodo “release” da invocare manualmente, rendendo così l’utilizzo di questo sistema soggetto ai soliti errori di memory leak, e quindi inutile.

Così ho cominciato a ragionare in C++: il meccanismo più efficiente per abbattere i costi dell’allocazione di memoria (in particolare la copia di oggetti complessi) è l’utilizzo di referenze come parametri di funzioni che consentono un comportamento “Java like” (e quindi il polimorfismo…) in modo totalmente trasparente al programmatore (che non deve gestire cioè manualmente la memoria): il limite delle referenze è che funzionano solo in una direzione (verso l’alto dello stack) e quindi non possono essere utilizzate per delle object factory. La soluzione è utilizzare gli auto_ptr, per consentire l’utilizzo di simil-referenze anche verso il basso dello stack: è così possibile creare una funzione del tipo:auto_ptr<resourcehandler> getResource(…);

A questo punto il distruttore di ResourceHandler avrà il compito di “rilasciare” la risorsa dal pool, e questo rilascio avverrà in automatico all’atto dell’uscita dallo scope dell’auto_ptr (bisogna quindi definire come virtuale il distruttore, per poter specializzare liberamente ResourceHandler).

Rimane però un problema: gli auto_ptr non possono essere utilizzati nei contenitori stl standard (o forse si… non mi ricordo come funzionano gli allocatori…). Certo che se Java mettesse a disposizione una callback tipo “finalize” (chiamiamola “referenceOutOfScope”) all’uscita dello scope di una referenza, il suo potenziale espressivo crescerebbe molto, mantenendo comunque la semplicità della gestione automatica della memoria.

sabato 20 gennaio 2007

Open Terracotta

Open source and the low cost of hardware capable of advanced features - such as main boards with integrated RAID controllers, multi core processors, faster and larger RAM modules (features that few years ago were offered only on high level systems), are now offering the chance to get impressive fault tolerance and clustering features on non-dedicated systems; lots of applications like web services could gain great benefit from this kind of features, and even new approaches to normal office applications became possible: with the reliability and performance of a high end system, it is possible to implement departmental web implementations of word processors or spreadsheet with a low enough cost to compete with the licensing cost of traditional office suites. Up to now I've been thinking of cluster able software as a clustering engine (an API) used in a custom designed application: something like an application with transactions or similar constructs used to keep consistency through the various nodes of the cluster. Up to now.
Yesterday, Jonas Boner from Terracotta Inc., presented in occasion of the Turin JUG meeting, gen. 2007, Open Terracotta. Please, have a look at it! terracotta.org.
One important thing Jonas was saying is that Open Terracotta is proposing a model of clustering/replication of enterprise Web 2.0 applications based on two layers: the usual database, which is responsible to maintain clustering/replication for the persistence layer - that is the data you usually store in the DB, and Terracotta, which is aimed to maintain consistency through cluster nodes for the Session Data – that is the data about the user logged in.
I think this kind of approach is the most effective, and fits perfectly in a Web 2.0 application. But what about other contests? First of all it's important to focus on the reasons that are leading to a clustering choice: it is a matter of scaling capability, fault tolerance, or both? It's very important to understand that in the case fault tolerance becomes a concern, a “software only” solution could not be sufficient, exposing for example the network layer as a SPOF; in this contest, software becomes part of the system (and not the system itself), so the whole system must be designed as a fault tolerant composition of software AND hardware. Assumed this, I still see in Terracotta a great and easy (for the developer) way to write software focusing on the business domain instead of having to deal with the technical detail of managing replication consistency.

Java was the first language I used with an integrated concurrency model (synchronized keyword, wait() and notify(), the new concurrent package): I thought this was such a leap forward for programmers, but yesterday we discussed the “what if” scenario in which Terracotta's heap consistency clustering approach is plugged inside the open source JVM; this could lead to new great applications! Imagine how easy could be to implement a chat system, or in general any kind of application (client based or web based) using shared informations. But personally I think that Sun doesn't want to plug into the free VM features that it's willing to sell to its customers!

venerdì 12 gennaio 2007

JUG gennaio 2007

Venerdi' 19 gennaio 2007 sera... da segnare in agenda: si va tutti al JUG! Vietato mancare!

http://www.jugtorino.it/vqwiki/jsp/Wiki?MeetingGennaio2007

mercoledì 13 dicembre 2006

Java SE 6

Sun has just released Mustang, after opening Java through an open source license; two great news in a short time, means something is changing... will this be Sun's response to Vista? First of all, Mustang's enhancements are focused on the desktop (we have a better look with LCD subpixeling, better OS theme support, tray icons and a great speed improvement) and I guess that, after having satified the server side with EE, Java is aiming to the desktop, client and stand alone applications. And most of these applications will run on Vista; so what if a lot of people starts using Java applications on Win which can be ported without any effort on Linux? Sun is offering also Ubuntu as a choice of OS on its systems...
GNU/Linux and Open Source is getting better and betters, and a good, really good alternative to Vista!
Only one thing... on my Fedora 6, Mustang's window repaint is not working with Compiz...

lunedì 27 novembre 2006

Method invocation in queries

In my object persistence engine I expect to be able to submit queries which can call methods on the stored objects:


SELECT Class c WHERE c.method();


Let's try to classify methods by their arguments, return values and side effects: the simplest kind of method I can use in a query is a “const” method (a method which doesn't modify the internal state of the objects) which returns a boolean and doesn't expect any argument. Such a method can be easily and safely be invoked during query execution, as it doesn't modify the object and is quite easy to evaluate. Methods that return something different from a boolean value, could cause problems during the evaluation of the WHERE clause. Also, methods expecting arguments could be difficult to evaluate as the query engine needs a mechanism to choose what argument to pass. But the most problematic type of method is the “non-const”, which modifies its internal state during the execution: this could require the query to re-evaluate some previously evaluated objects, or if the evaluated object modifies some other related object contained in the database could cause a cascade update, which could be difficult to handle. And, even worse, a method could throw an exception! But how to handle it?

  • Constness: if not const, could cause cascade modifications on the persistence layer
  • Return value: if not boolean (or primitive) could cause difficult evaluation
  • Arguments: if needed, could cause difficulties for the query engine to choose which
  • Exceptions: could cause difficulties in the execution thread

venerdì 24 novembre 2006

Object ID

9223372036854775807 is the maximum value of a Java long. It should be a sufficiently big number to be used for object identification in my ODBMS (well, actually it's an object persistence and query engine, but it could be used by a fully featured object oriented database management system in the future).
I'd like to be able to use consecutive numbers starting from 0 but I need an efficient hash function for indexing: the java.lang.Long's hashCode() won't do the work as it just returns a xor of the two halves of the value, so I was thinking about using something like this function - look for hash64shitf(long key).
Let's do some speed tests:
5 millions of hash values calculated with the hash64shit() took ~= 2450 mills, while the usual Long.hashCode() took 422 mills. Sure, the weak hash function is much faster, but 2,5 seconds for computing 5M hash keys is quite a small amount of CPU time!

giovedì 23 novembre 2006

Using the file system as a persistence engine for a database

I'm currently designing a sort of object oriented database engine in Java. I'd like to have a plug-in design for all the components, so that I can choose to implement them as I want. Now I'm thinking about the persistence engine, and I'd like to approach the problem with a different perspective; let's see what are the features I'd like to obtain from this component: first of all I'd like to implement it easily, then I'd like it to be enough performing to be usable not only for example purpose; I want caching, expandability, eventually replication and multi-volume. I've started thinking about an “ad hoc” file format, but its design is not so trivial: deleting records could cause an inefficient use of the space, and eventually fragmentation; and caching could be a nice problem too. Having to deal with this problems ain't that easy, which means that this approach could cause a big amount of time spent. So is there any thing able to perform this sort of operations efficiently? Sure: the file system! Modern file systems (have a look at Sun's ZFS ) do offer a lot, and they are virtually free, in the sense that any modern OS offers a set of features that include caching, mirroring, space saving features such as compression, and even security features such as journalling, error recovery and file content encryption.
So the choice is done, I'll think about a persistence engine based on the file system and directory structure (I could implement inheritance via subdirectory organization, and object reference with simple urls or links).