вівторок, 27 листопада 2012 р.

Maven 2 and later generating version with svn revision number

Формирование номера версии включающего в себя номер текущей ревизии из svn можно организовать с помощью maven плагина buildnumber-maven-plugin. Сформируем строку версии следующего вида: Release Info (Build Date: Nov 27, 2012 11:22:00.000 Build Number 12) При этом переменными данными являются дата и номер ревизии. В главный, если проект мультимодульный, pom файл необходимо добавить следующий код:

    scm:svn:https://somePath/trunk
    scm:svn:https://somePath/trunk
    scm:svn:https://somePath/trunk


    ...
    
        ...
        
            org.codehaus.mojo
            buildnumber-maven-plugin
            1.1
            
                
                    Generate build revision
                    validate
                    
                        create
                    
                    
                        true
                        buildRevision
                        false
                        false
                        true
                    
                
                
                    Generate build timestamp
                    validate
                    
                        create
                    
                    
                        buildDate
                        {0,date,MMM dd',' yyyy HH:mm:ss.SSS}
                        en
                        
                            timestamp
                        
                        false
                        false
                        true
                    
                
            
        
    


Адреса svn репозитория могут быть любыми mock адресами, потому как для получения номера последней ревизии используется номер ревизии из локальной копии. Что позволит иметь номер ревизии именно того кода, который в данный момент собирается.
После чего в каком-либо properties файле можно использовать следующие свойства:
app.version=Release Info (Build Date: ${buildDate} Build Number ${buildRevision})

вівторок, 14 серпня 2012 р.

JPA @Id with @ManyToOne

Использовать одновременно аннотации @Id и @ManyToOne на одном и том же поле невозможно. Поэтому необходимо использовать EmbeddedId. Тогда конструкция вида:
@Entity
public class Foo {

    @Id
    @ManyToOne
    @JoinColumn(name = "key", nullable = false)
    private int externalKey;

    @Column
    private String value;
    
    ...
}

Принимает вид:
@Entity
public class Foo {

    @Embeddable
    public static class Pk implements Serializable {

        @ManyToOne
        @JoinColumn(name = "key", nullable = false)
        private int externalKey;

        ...
    }

    @Column
    private String value;

    @EmbeddedId
    private Pk pk;
    
    ...
}

пʼятниця, 20 липня 2012 р.

Создание custom application launcher в Ubuntu 12.04 + unity

Для добавления кастомного лаунчера в док unity необходимо создать файл launcherName.desktop и заполнить его следующим содержанием:


[Desktop Entry]
Encoding=UTF-8
Name=Launcher Name
Comment=Some comments
Exec=/bin/sh "path/to/users/custom/sh/app"
Icon=/path/to/yours/app/icon/path
Categories=Category1;Category2
Version=1.0
Type=Application
Terminal=0

Свойству "Exec=" необходимо прописать путь к выполняемой команде. Если это linux команда, необходимо просто указать полный путь к ней. Если же необходимо запускать какое-то sh приложение, используем стандартную команду /bin/sh и передаем ей требуемые аргументы.
После чего установить флаг разрешения запуска в свойствах файлах и можно спокойно перетягивать созданный файл на unity док. После чего запускать приложения/выполнять команды и т.п. прямо с дока.

вівторок, 17 липня 2012 р.

Spring 3 + Hibernate + EntityManager autoscan entities

Возникают ситуации, когда entities находятся в неожиданном для Spring месте, и он не может их найти и объяснить hibernate где же их искать. Поэтому, что бы не указывать в файле persistance.xml все используемые entity, можно научить Spring искать их в заданном пакете.

Для этого необходимо создать свой bean, в котором указать пакет с enities:

<bean id="entitiesScanner" class="org.myapp.utils.EntitiesScanner">
     <property name="packagesToScan">
          <list>
               <value>org.some.greate.package</value>
          </list>
     </property>
 </bean>


А в bean LocalContainerEntityManagerFactoryBean добавить следующий аргумент:

<property name="persistenceUnitPostProcessors">
     <list>
          <ref bean="entitiesScanner"/>
     </list>
</property>


Ну и создать класс собственно EntitiesScanner:

import org.hibernate.MappingException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
import org.springframework.util.ClassUtils;

import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

public class EntitiesScanner implements ApplicationContextAware, PersistenceUnitPostProcessor {

    private static final String RESOURCE_PATTERN = "**/*.class";
    private ApplicationContext applicationContext;
    private String[] packagesToScan;
    private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    private TypeFilter[] entityTypeFilters = new TypeFilter[]{
            new AnnotationTypeFilter(Entity.class, false),
            new AnnotationTypeFilter(Embeddable.class, false),
            new AnnotationTypeFilter(MappedSuperclass.class, false)};

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
        String[] entities = scanPackages();
        for (String entity : entities) {
            pui.addManagedClassName(entity);
        }
    }

    /**
     * Set whether to use Spring-based scanning for entity classes in the
     * classpath instead of listing annotated classes explicitly.
     * <p/>
     * <p/>
     * <p/>
     * Default is none. Specify packages to search for autodetection of your
     * entity classes in the classpath. This is analogous to
     * <p/>
     * Spring's component-scan feature
     * (org.springframework.context.annotation.ClassPathBeanDefinitionScanner}).
     */
    public void setPackagesToScan(String[] packagesToScan) {
        this.packagesToScan = packagesToScan;
    }

    /**
     * Perform Spring-based scanning for entity classes.
     *
     * @see #setPackagesToScan
     */
    protected String[] scanPackages() {
        Set<String> entities = new HashSet<String>();
        if (this.packagesToScan != null) {
            try {
                for (String pkg : this.packagesToScan) {
                    String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                            + ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN;
                    Resource[] resources = this.resourcePatternResolver.getResources(pattern);
                    MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
                    for (Resource resource : resources) {
                        if (resource.isReadable()) {
                            MetadataReader reader = readerFactory.getMetadataReader(resource);
                            String className = reader.getClassMetadata().getClassName();
                            if (matchesFilter(reader, readerFactory)) {
                                entities.add(className);
                            }
                        }
                    }
                }
            } catch (IOException ex) {
                throw new MappingException("Failed to scan classpath for unlisted classes", ex);
            }
        }
        return entities.toArray(new String[entities.size()]);
    }

    /**
     * Check whether any of the configured entity type filters matches the
     * current class descriptor contained in the metadata
     * <p/>
     * reader.
     */
    private boolean matchesFilter(MetadataReader reader, MetadataReaderFactory readerFactory) throws IOException {
        if (this.entityTypeFilters != null) {
            for (TypeFilter filter : this.entityTypeFilters) {
                if (filter.match(reader, readerFactory)) {
                    return true;
                }
            }
        }
        return false;
    }
} 

via Spring, JPA, Hibernate Best Practices and Tips 

Но если вы используете spring 3.1.1, то достаточно такого конфига:

<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceProviderClass"
                  value="org.hibernate.ejb.HibernatePersistence"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.connection.datasource">${hibernate.connection.datasource}</prop>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.show.sql">${hibernate.show.sql}</prop>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            </props>
        </property>

        <property name="packagesToScan">
            <list>
                <value>com.package.enities</value>
            </list>
        </property>
    </bean>

При этом от pesistence.xml можно полностью отказаться.

середа, 11 липня 2012 р.

Получем Session из EntityManager


HibernateEntityManager hem = em.unwrap(HibernateEntityManager.class);
Session session = hem.getSession();


И можем использовать красивые критерии.
via http://stackoverflow.com/

понеділок, 14 травня 2012 р.

Молярная масса доменного газа

Состав, согласно википедии: 12-20 % СО2; 20-30 % СО; до 0,5 % СН4; 1-4 % Н2; 55-58 % N2.
Усредняем количества: СО2 - 16%, СО - 25%, N2 - 56%, Н2 - 3%.
Имеем молярные массы компонентов: С - 12, N - 14, О - 16, Н - 1.
Имеем формулу для расчета молярной массы газовой смеси:
0.16 * (12 + 2 * 16) + 0.25 * (12 + 16) + 0.56 * (2 * 14) + 0.03 * (2 * 1) = 29.78