Studio

Posted on June 24th, 2009 in Photo, RU | No Comments »

Впервые после Мишиных семинаров снимал в оборудованной студии. Ощущения феерические.

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • Technorati
  • Reddit
  • Scoopeo

Пока еще актуально

Posted on November 3rd, 2008 in RU | No Comments »

“… На выборах за кого голосовать - за Барака? Или за Обаму?”

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • Technorati
  • Reddit
  • Scoopeo

JTL goes open-source

Posted on September 6th, 2008 in EN, Java, Tools | No Comments »

JTL, the Java Tools Language (pronounced “Gee-tel”), is a high-level query language for selecting program elements, designed to serve the development of source code software tools for Java.
It is both simple and powerful: you may use it for various source code tasks, from just finding all classes with print() method to executing an extremely complex refactoring transformation.

JTL is very easy to use, its intuitive query-by-example syntax makes it really easy to write JTL queries. For example,

public static double method(int, int);

matches all static methods that receive two int parameters and return a double. And the following query

classWithFactory := is T, class { 
    no public constructor; 
    public static T method;
}

matches all factory classes - classes having no public constructor, but instance factory method.

Additional JTL examples may be found in JTL Language Tour. The examples above come from this excellent manual too.

The JTL was initially described in the JTL - The Java Tools Language paper and developed at the Computer Science department at the Technion. But now, after a years of development, JTL goes open source at sourceforge. There is no blog or RSS feed there yet, but I hope those will appear soon.

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • Technorati
  • Reddit
  • Scoopeo

Online unique identity is not here yet

Posted on July 26th, 2008 in Blogging, EN | No Comments »

Though claiming a blog at Technorati Profile is not so painful a it looks.

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • Technorati
  • Reddit
  • Scoopeo

Hibernate annotations: The many-to-many association with composite key

Posted on July 19th, 2008 in EN, Java, Tools | 49 Comments »

Also many-to-many associations are usually referenced as a bad design solution, they are widely used in almost all modern database-centric applications (especially in those built around the existing legacy database). The very common scenario is a case when you not only need to handle a many-to-many association but also hold some additional property on the association.

In a J2EE world, Hibernate still remains the most popular ORM tool (or the JPA provider, if you wish). But implementing such a scenario with Hibernate Annotations is not so simple as you might imagine.

First of all, in the good old spirit of the Hibernate community, there is almost no documentation about many-to-many associations and composite keys (two paragraphs stating that there is @ManyToMany and @EmbeddedId annotations are not considered a documentation).

And the second hope of every open-source tool consumer, the world wide web community, provides almost no help: everybody are referencing the same post by Marcel Panse, written in April 2006. Though Marsel’s post is very clean and descriptive, it become outdated and the solution provided there is simply not working with the latest versions of Hibernate Annotations.

So I had to reinvent the wheel by my own, based on Marsel’s sample. Below is the solution working with Hibernate Annotations 3.3.1.GA.

The database part is the same: we have three tables (item, product and product_item), two POJO classes, and two classes for a many-to-many association and its primary key. The main difference from Marsel’s solution is that I’m not using any kind of “fake” properties on ProductItem in order to reference Item and Product, but just a plain transient properties delegating to ProductItemPk.

@Entity
@Table(name = "item")
public class Item {
 
    private Integer id;
    private String name;
    private List<ProductItem> productItems = new LinkedList<ProductItem>();
 
    public Item() {
    }
 
    @Id
    @GenericGenerator(name = "generator", strategy = "increment")
    @GeneratedValue(generator = "generator")
    @Column(name = "item_id", nullable = false)
    public Integer getId() {
        return this.id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    @Column(name = "name")
    public String getName() {
        return this.name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.item")
    public List<ProductItem> getProductItems() {
        return this.productItems;
    }
 
    public void setProductItems(List<ProductItem> productItems) {
        this.productItems = productItems;
    }
}
@Entity
@Table(name = "product")
public class Product {
 
    private Integer id;
    private String name;
    private List<ProductItem> productItems = new LinkedList<ProductItem>();
 
    public Product() {
    }
 
    @Id
    @GenericGenerator(name = "generator", strategy = "increment")
    @GeneratedValue(generator = "generator")
    @Column(name = "product_id", nullable = false)
    public Integer getId() {
        return this.id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    @Column(name = "name")
    public String getName() {
        return this.name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.product")
    public List<ProductItem> getProductItems() {
        return this.productItems;
    }
 
    public void setProductItems(List<ProductItem> productItems) {
        this.productItems = productItems;
    }
}

Note the two important points: ProductItem has two transient properties for Product and Item (since an unidirectional relationships will be meaningless here) and a use of @AssociationOverrides annotation to specify the database columns

@Entity
@Table(name = "product_item")
@AssociationOverrides({
@AssociationOverride(name = "pk.item", joinColumns = @JoinColumn(name = "item_id")),
@AssociationOverride(name = "pk.product", joinColumns = @JoinColumn(name = "product_id"))
        })
public class ProductItem {
 
    private ProductItemPk pk = new ProductItemPk();
 
    @EmbeddedId
    private ProductItemPk getPk() {
        return pk;
    }
 
    private void setPk(ProductItemPk pk) {
        this.pk = pk;
    }
 
    @Transient
    public Item getItem() {
        return getPk().getItem();
    }
 
    public void setItem(Item item) {
        getPk().setItem(item);
    }
 
    @Transient
    public Product getProduct() {
        return getPk().getProduct();
    }
 
    public void setProduct(Product product) {
        getPk().setProduct(product);
    }
 
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
 
        ProductItem that = (ProductItem) o;
 
        if (getPk() != null ? !getPk().equals(that.getPk()) : that.getPk() != null) return false;
 
        return true;
    }
 
    public int hashCode() {
        return (getPk() != null ? getPk().hashCode() : 0);
    }
}
@Embeddable
public class ProductItemPk implements Serializable {
 
    private Item item;
    private Product product;
 
    @ManyToOne
    public Item getItem() {
        return item;
    }
 
    public void setItem(Item item) {
        this.item = item;
    }
 
    @ManyToOne
    public Product getProduct() {
        return product;
    }
 
    public void setProduct(Product product) {
        this.product = product;
    }
 
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
 
        ProductItemPk that = (ProductItemPk) o;
 
        if (item != null ? !item.equals(that.item) : that.item != null) return false;
        if (product != null ? !product.equals(that.product) : that.product != null)
            return false;
 
        return true;
    }
 
    public int hashCode() {
        int result;
        result = (item != null ? item.hashCode() : 0);
        result = 31 * result + (product != null ? product.hashCode() : 0);
        return result;
    }
}

Hope this helps.

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • Technorati
  • Reddit
  • Scoopeo

Как много нам открытий чудных

Posted on May 19th, 2008 in RU | No Comments »

После бурного обсуждения на работе выяснилось, что я делаю это не с той стороны, с которой это делают мои коллеги.
Чувствую себя остроконечником.

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • Technorati
  • Reddit
  • Scoopeo

Смотреть на жизнь через объектив.

Posted on April 30th, 2008 in RU | No Comments »

Объявление: “Ищется няня для ребенка 2.8″.
Странно, думаю, а почему фокусное расстояние не указано?

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • Technorati
  • Reddit
  • Scoopeo

Два мира, два.

Posted on April 18th, 2008 in RU | No Comments »

Утро, еду на работу. Полупустой вагон, в ушах - наушники, перед глазами - лептоп.
Через несколько сидений от себя замечаю религиозного мужика, накладывающего тфилин.
Всю дорогу каждый занят своим делом: мужик сосредоточено молится, я — читаю статью.
“Уважаемые пассажиры, бла, бла бла”. Ну, приехали наконец-то. Закрываю лептоп, сматываю провод от наушников. Напротив меня мужик абсолютно синхронно со мной закрывает молитвенник и начинает сматывать тфилин. Вытаскиваем сумки, упаковываемся, встаем и продвигаемся на выход.

Бонус: Qumran community: The Phylactery Scroll.

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • Technorati
  • Reddit
  • Scoopeo

Good coders, maybe. Awful product managers, definetely.

Posted on April 3rd, 2008 in EN, Technical | No Comments »

The discussion is probably one of the best examples to the simple rule: programmers should never ever be allowed to lead a product design.

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • Technorati
  • Reddit
  • Scoopeo

Настройка OpenID на своем сайте

Posted on March 29th, 2008 in LiveJournal, OpenID, RU, WordPress | 3 Comments »

Для тех кто совсем не в курсе: OpenID — это открытая децентрализованная система единого входа, которая позволяет использовать один логин и пароль на большом количестве сайтов, которую придумал, угадайте кто (нет, не самизнаетекто, а Бред).

Для гиков, фриков и прочих тех, кому не лень: можно настроить у себя на сайте свой собственный OpenID провайдер с помощью phpMyID или PHP Standalone OpenID Server. Желаю успеха. Настроите - приходите, расскажете как было.

А для ленивых вроде меня: проще всего воспользоваться одним из существующих провайдеров и только немного подкрутиь свой сайт. Я настраивал свой блог на Wordpress 2.3.3 с помощью провайдера myOpenID

Первое: регистрируем. Заходим на https://www.myopenid.com/ и регистрируемся. В конце регистрации получаем свой собственный OpenID, например http://pupkin.myopenid.com. В принципе, с этим ID уже можно заходить на сайты, комментировать в ЖЖ и в этом блоге и прочая.

Второе: настраиваем. Делаем так, чтбы вместо http://pupkin.myopenid.com можно было писать http://vasya.pupkin.com. Для этого идем на свой сайт http://vasya.pupkin.com и вставляем в таг <head> следующие строчки:

<!-- Start myOpenId settings -->
<link rel="openid.server"
       href="http://www.myopenid.com/server" />
<link rel="openid.delegate"
       href="http://pupkin.myopenid.com/" />
<link rel="openid2.local_id"
       href="http://pupkin.myopenid.com" />
<link rel="openid2.provider"
       href="http://www.myopenid.com/server" />
<meta http-equiv="X-XRDS-Location"
         content="http://www.myopenid.com/xrds?username=pupkin.myopenid.com" />
<!-- End myOpenId settings -->

И компот третье: проверяем. Идем в ЖЖ, или в комментарии к этой записи, или еще куда (в смысле, где можно заходить в OpenID, а не то, что вы подумали). В поле, которое отмечено значком пишем http://vasya.pupkin.com и жмем на логин. Вас должно перебросить на страницу myOpenID для логина, а потом обратно, на страницу с комментариями.

Вот и все.

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Facebook
  • Google
  • Technorati
  • Reddit
  • Scoopeo