Показаны сообщения с ярлыком Knowhow. Показать все сообщения
Показаны сообщения с ярлыком Knowhow. Показать все сообщения

понедельник, 20 февраля 2012 г.

Hibernate Proxy

Есть много нюансов с прокси объектами. Кроме того что они протухают, их equals метод может удивить, т.к. отличается от equals клёвого объекта. Так, он по умолчанию сравнивает все поля клёвого объекта, что может привести к лэйзиинициалиэйшн и тп.

Вот тут в тему, рядом.
http://blog.xebia.com/2008/03/08/advanced-hibernate-proxy-pitfalls/

P.S. Hibernate.initialize(..) инициализирует сам прокси, но не меняет его equals, так же как не инициализирует его lazy поля.

воскресенье, 9 октября 2011 г.

Motorola DEFY Fuck/Flashing

  Изначально в телефоне была прошивка ANDROID 2.1(BLUR)
Которая как то работала, правда после 2-3 дней работы начинала здорово подтормаживать - переставали нормально работать самые нужные телефонные функции, так например при входящем звонке нажатие на кнопку ответа подвисало секунд на 20, а за это время звонок успевали уже сбросить. Установка всячиских приблуд(типа систем тюнеров и таск мэнеджеров), удаление виджетов и хард ресеты ситуацию не исправили. Прошивка на 2.2(BLUR) только усугубила ситуацию. Стали жёстко тормозить Google Maps и вообще вес интерфейс.
В итоге решил попробовать перепрошиться с 2.2 на 2.3.  Поскольку официальных прошивок не было, да и MOTOBLUR был первым кандидатом на роль источника тормозов, начал исследования  любительских прошивок.  После изучения возможных вариантов выбрал
MIUI от Kojan 1.10.7(8). Перебрал разные варианты софта в итоге нашёл более менее правильное(простое) решение.

1. Установка root
Использовал утилиту SuperOneClick.
Качаем её с родного сайта ftp://shortfuse.org/SuperOneClick/Packages/
И читаем http://4pda.ru/forum/index.php?showtopic=200800&st=220
http://forum.xda-developers.com/showthread.php?t=803682
Перед установкой необходимо поставить 
NET.Framework, JDK 1.6 , Android SDK

2. Установка загрузчика
Скачиваем 2ndInit через AndroidMarket.
http://forum.xda-developers.com/showthread.php?t=1032212
http://www.appbrain.com/app/defy-2ndinit/com.pedronveloso.sndinitdefy
Запускаем его как обычную программу и инсталируем последнюю версию. 
В 2ndInit встроен ClockworkMod Recovery, который используется для бэкапов и перепрошивки.


3. Бэкап
Делается после перезагрузки телефона в меню 2ndInit.

4. Перепрошивка
Делается через меню 2ndInit
Про разные прошивки можно почитать тут
http://4pda.ru/forum/index.php?showtopic=239103&st=560#entry8883267
Выбрал эту
MIUI от Kojan 1.10.7(8).

среда, 10 августа 2011 г.

SOAPFaultException на платформах .NET и Java, опыт работы с JAX-WS

На днях поимел опыт работы с вебсервисами из коробки-моробки JAX-WS.


1. Все исключения выбрасываемые эндпоинтом нужно делать кастомными и аннотировать
@WebFault(name = "CRUDSoapException", targetNamespace = "wsdl.xxx")
см. блог Eben Hewitt 

Иначе на клиента вываливается SOAPFaultException с кускокм строкового говна, который как бы описывает иксэпшн.

2. Все исключения  выбрасываемые эндпоинтом приходят на платформу .NET в виде строкового
 говна (обёрнутого в SOAPFaultException) в не зависимости от способа объявления на эндпоинте.

3.JAX-B может зажевать исключения возникающие при сериализации, и чтобы таки их увидеть нужно включить такой параметр в запуск программы  -Djavax.net.debug=all

4. JAX-B не умеет сериализовать прокси объекты Hibernate (да и вообще - наверное любые сгенерённые прокси). Бороть  так converting-hibernate-proxy-to-real-object
5. JAX-B не умеет сериализовать интерфейсы.  Если есть необходимость использовать интерфейс можно сделать абстрактный класс реализующий этот интерфейс и обвесить его JAX-B аннотациями(@XmlSeeAlso - с указанием классов). В дальнейшем в коде можно будет использовать этот интерфейс добавив для него частный @XmlJavaTypeAdapter, который будет тупо преобразовывать абстрактный класс в интерфейс. 




воскресенье, 20 марта 2011 г.

Наибольшая общая подпоследовательность


public class SequenceTest {
                      //0  1   2  3   4  5  6  7   8
    static int[] qwe = {1, 4, -6, 2, -1, 5, 2, 0, -6};
    //static int[] qwe = {1, 2, 3, 4, 5, 6, 7};

    @Test
    public void test() {

        int maxSum = 0;
        int i1 = 0;
        int i2 = 0;

        int newSum = 0;
        int i1n = 0;
        int i2n = 0;

        for (int i = 0; i < qwe.length; i++) {
            int x = qwe[i];
            if (newSum == 0) {
                i1n = i;
            }
            i2n = i;

            int current = newSum + x;
            if (current > newSum) {//подпоследовательность растёт
                newSum = current;
            } else {//подпоследовательность начала уменьшаться

                if (newSum > maxSum) {//если сумма текущей подпоследовательности больше чем maxSum - запомним её
                    maxSum = newSum;
                    i1 = i1n;
                    i2 = i2n;
                }
                if (current <= 0) {//если подпоследовательность меньше 0 она уже не может быть полезной
                    newSum = 0;
                    i1n = 0;
                    i2n = 0;
                } else {//продолжаем рассматривать уменьшающуюся последовательность
                    newSum = current;
                }
            }
        }

        if (maxSum == 0 && newSum > 0) {
            maxSum = newSum;
            i1 = i1n;
            i2 = i2n;
        }

        System.out.println(i1 + "-" + i2 + "  maxSum:" + maxSum);
    }
}


среда, 16 марта 2011 г.

XStream vs Simple

XStream  быстрее чем Simple приблизительно в два раза. Тестил под Windows. Для теста были созданы сущности с дублирующими друг друга аннотациями для XStream и Simple.




Класс тестика:
package ru.test.serialization;



import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.*;
import org.junit.Test;
import org.simpleframework.xml.convert.AnnotationStrategy;
import org.simpleframework.xml.core.Persister;
import org.simpleframework.xml.strategy.Strategy;
import java.io.StringWriter;
/**
 * @author k.burmistrov
 */
public class SimpleVSXstream {
        @Test public void test() {
        XStream xStream = new XStream(new DomDriver());
        Persister serializer = new Persister();
        long smplstart;
        long smplexecTime = 0;
        Container container;
        long xsstart;
        long xsexecTime = 0;
        String res = "";
        for (int i = 0; i < 100; i++) {
            container = ContainerCreator.getContainer();
            xsstart = System.currentTimeMillis();
            res = xStream.toXML(container);
            xsexecTime = xsexecTime + (System.currentTimeMillis() - xsstart);
            StringWriter writer = new StringWriter();

            try {

                smplstart = System.currentTimeMillis();
                serializer.write(container,writer);
            } catch (Exception e) {
                smplstart = System.currentTimeMillis();
                e.printStackTrace();
            }
            res = writer.toString();
            smplexecTime = smplexecTime + (System.currentTimeMillis() - smplstart);
        }

        System.out.println( "XSTREAM x 100 = " + xsexecTime);

        System.out.println( "SIMPLE x 100 = " + smplexecTime);

        System.out.println("\n" + ContainerCreator.toDebugString(res));
    }
}
Результирующий вывод:
XSTREAM x 100 = 138 SIMPLE x 100 = 213




<CONTAINER PART="0">
   <BIG CODE="String code 50.35868861427403564" LOGIN="String login 50.7245088483040268" SUBADDRESS="0">
      <PART PART="0" SERIAL="0"/>
      <BIG CODE="String code" LOGIN="String login" SUBADDRESS="0">
         <PART PART="0" SERIAL="0"/>
      </BIG>
      <BIG CODE="String code 10.06973240045944129" LOGIN="String login 10.9788960825360289" SUBADDRESS="0">
         <PART PART="0" SERIAL="0"/>
      </BIG>
      <BIG CODE="String code 20.627970543681521" LOGIN="String login 20.5815827829176397" SUBADDRESS="0">
         <PART PART="0" SERIAL="0"/>
      </BIG>
      <BIG CODE="String code 30.9800044849451679" LOGIN="String login 30.5987182743788726" SUBADDRESS="0">
         <PART PART="0" SERIAL="0"/>
      </BIG>
      <BIG CODE="String code 40.9685538564759587" LOGIN="String login 40.11954755881153056" SUBADDRESS="0">
         <PART PART="0" SERIAL="0"/>
      </BIG>
   </BIG>
   <BIG CODE="String code 60.9978869534936364" LOGIN="String login 60.22744058846132909" SUBADDRESS="0">
      <PART PART="0" SERIAL="0"/>
      <BIG CODE="String code" LOGIN="String login" SUBADDRESS="0">
         <PART PART="0" SERIAL="0"/>
      </BIG>
      <BIG CODE="String code 10.06973240045944129" LOGIN="String login 10.9788960825360289" SUBADDRESS="0">
         <PART PART="0" SERIAL="0"/>
      </BIG>
      <BIG CODE="String code 20.627970543681521" LOGIN="String login 20.5815827829176397" SUBADDRESS="0">
         <PART PART="0" SERIAL="0"/>
      </BIG>
      <BIG CODE="String code 30.9800044849451679" LOGIN="String login 30.5987182743788726" SUBADDRESS="0">
         <PART PART="0" SERIAL="0"/>
      </BIG>
      <BIG CODE="String code 40.9685538564759587" LOGIN="String login 40.11954755881153056" SUBADDRESS="0">
         <PART PART="0" SERIAL="0"/>
      </BIG>
   </BIG>
</CONTAINER>



PS: значение атрибутов генериловалось для каждой итерации новое





вторник, 8 февраля 2011 г.

SQL Поиск дырок

Задача:  в последовательности айдишников найти пропуски.

Пример 1: Дырка в одну цифру. 


В таблице "_IDCHECK" нужно
Найти 6.

Наверное проще всего это сделать при помощи left outer join.
Джоиним таблицу саму с собой со сдвигом на 1.
Чтобы понять как это работает сначала посмотрим результаты такого запроса


select a.id, b.id
from "_IDCHECK" as a
left outer join "_IDCHECK" as b on (a.id+1) = (b.id)



Осталось выбрать столбцы где  b.id == null


select a.id+1
from "_IDCHECK" as a
left outer join "_IDCHECK" as b on (a.id+1) = (b.id)
where b.id is null

И убрать последнее значение


select a.id+1
from "_IDCHECK" as a
left outer join "_IDCHECK" as b on (a.id+1) = (b.id)
where b.id is null  and a.id<(select max(id) from "_IDCHECK" )

ЗЫ: тоже самое можно написать через select


select a.id+1 from "_IDCHECK" as a
  where not exists(select * from "_IDCHECK" as b where b.id=a.id+1)








среда, 29 сентября 2010 г.

BufferedImage getType() returns 0

0 это BufferedImage.TYPE_CUSTOM. С таким типом ряд операций(ресайз/скэйл и тп) с изображением сделать проблематично -   все попытки закончатся 
- java.lang.IllegalArgumentException: Unknown image type 0
Фигня возникла при работе с PNG, причём для одинаковых файлов на разных java машинах возвращался разный тип(TYPE_3BYTE_BGR(5) на jdk 1.6.0_19 и TYPE_CUSTOM(0) на jdk 1.6.0_13 ) .
Для получения BufferedImage  использовался 





   ImageIO.read(new File(configuration.getPath()))
Нашёл следующее  лекарство - определять тип картинки ручками. Лекарство видимо будет помогать только при некоторых случаях. Тип определяется так:





bufferedImage.getColorModel().hasAlpha() ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR;
Лекарство нашёл тут:








вторник, 31 августа 2010 г.

Двойной диспатч как средство борьбы с неопределённостью типов при компиляции

-----------------------------------------------------
...Ласковое дуновение ветра коснулось выдубленной солнцем и непогодой красной кожи седого индейца. Он поморщился, как будто почувствовал в воздухе что-то неприятное,  и вытянув губы в трубочку начал что то насвистывать себе под нос. Белый человек сидящий напротив него поднял глаза от костра,  упёрся взглядом в грубую тунику седого и задумчиво сказал
- Ты прав Бычий Хуй. Есть что то в двойном диспатче.
Бычий Хуй ничего не ответил. Смотря на пламя костра и продолжая насвистывать странную мелодию он полез за трубкой...
------------------------------------------------------

Двойной диспатч можно любить или не любить. Но ввиду особенностей работы c Java, есть несколько ситуаций, когда без него просто не обойтись. Например когда класс, параметризующий вызов метода, неизвестен при компиляции.

Пример:


    

    import org.junit.Test;

    public class TestABC {

        static class A {
        }
       static class B extends A {
       }
       static class C extends A {
           void print(ABC abc) {
               abc.print(this);
           }
       }
       static class ABC {
           void print(A a) {
               System.out.println("a");
           }   

           void print(B b) {
               System.out.println("b");
           }

           void print(C c) {
               System.out.println("c");
           }
       }


       @Test
       public void test() {

           ABC abc = new ABC();

           A a = new A();

           B b = new B();

           C c = new C();

           //----------------------

           System.out.println("-----------------------");

           abc.print(a);
           abc.print(b);
           abc.print(c);
           //-----------------------

           System.out.println("-----------------------");
            //будет вызван только метод void print(A a) 

           abc.print(a);
           abc.print((A) b);
           abc.print((A) c);

           //-----------------------

           System.out.println("-----------------------");

           ((A)c).print(abc);//вот он красавец - двойной диспатч
       }

   }

   


Вывод:


-----------------------
a
b
c
-----------------------
a
a
a
-----------------------
c






вторник, 29 июня 2010 г.

Hibernate and primitive type values

  Примитивные примитивы слишком примитивны для хибернэйта. Парадигму мозгоёбства можно описать следующей фразой одного эксперта:Hibernate doesn't care about values, just mappings(https://forum.hibernate.org/viewtopic.php?t=949814).Сказал в 2004 году - как отрезал. Ничего пока принципиально не поменялось. Геморой проистекает из того, что хибернэйт по-умолчнию вместо примитивных типов пишет в базу null. А потом приводит этот null к примитивам(например int). Так что вылетающие из недр хибернэйта
org.springframework.orm.hibernate3.HibernateSystemException: Null value was assigned to a property of primitive type setter of  MovableObject.movingStatus; nested exception is org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of MovableObject.movingStatus
-"это нормально".

Вообще хибернэйт не обладает magic свойствами, всё что он гарантирует в плане метаданных-
а)При начале работы с чистой бд все мапинги хибернэйта будут промаплены
б)При изменениее мапинга старые данные не будут утеряны

А это означает что изменение мапинга столбцов, таблиц и тп, на уже существующую бд через хибернэйт - будут "как то" применены. "Как-то" - по факту это добавление новых столбцов в таблицу, и сохранение метаданных старых.

Лечение. 

1) 100% лечение. Переписывем все геттеры. вместо примитивных типов используем врапперы (Integer) и делаем их проверку на null

    @Column(name = "OBJECTSTATUS")
    private Integer objectStatus ;


    public int getObjectStatus() {
        if (objectStatus == null) {
            objectStatus = 0;
        }
        return objectStatus;
    }

2) @Column(name = "OBJECTSTATUS", nullable = false)
Лечение работает при вставках новых объектов с незаданными полями, имеет ряд противопоказаний. При добавлении мапинга нового столбца лечение не сработает. Также оно вероятно не сработает если изменить мапинг уже существующей колонки(c firebird 2.1.3+hibernate 3.5.1 не сработает точно).
  
Так же присутствует полный просос при работе с наследованием по @DiscriminatorValue - поля которые казалось бы не используются в объектной модели, очень даже используются в таблицах и как результат - ошибки хибернэйта при попытках кастовать  нулл к примитивам.

3)@Column(name = "OBJECTSTATUS")
    private int objectStatus = 0;
Лечение работает при вставках новых объектов с незаданными полями 

   

Самым правильным наверное будет делать так:

  @Column(name = "OBJECTSTATUS")
    private Integer objectStatus=0;

    public int getObjectStatus() {
        if (objectStatus == null) {
            objectStatus = 0;
        }
        return objectStatus;
    }

-при вставках строк гарантируем что будет выставлен везде 0
-при вставке столбца  гарантируем что не возникнет ошибки и через геттер всегда получим дефолтное значение



PS.
1)прокачать знания про то как 6.2.1. Hibernate event-based validation 2)@NotFound(action=NotFoundAction.IGNORE) - это для объектов

понедельник, 21 июня 2010 г.

String.format depends on locality...

Неожиданно. Сужает область применения String.format до вывода в консоль.
public class xxx {
    @Test
    public void xxxx() {
        double xxx = 123.5657;
        System.out.println(Double.toString(xxx));
        //123.5657
        System.out.println(String.format("%.2f", xxx));//работет прально если Formatter formatter = new Formatter(sb, Locale.US)
        //123,57
        System.out.println((new BigDecimal(xxx)).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
        //123.57
        String.format("%.2f", xxx).replaceAll(",", ".");
        //123.57
    }
}

суббота, 23 января 2010 г.

How to set Spring bean properties

Казалось бы тривиальная задача. Но вот возникла проблема - а именно вопрос: Как передать в качестве параметров одного бина - параметры другого. Задача возникла исходя из желания конфигурировать org.springframework.beans.factory.config.PropertyPlaceholderConfigurer(умеет врапить проперти из всяких файлов типа config.properties в переменные applicationContext.xml) не из applicationContext.xml, а из командной строки при запуске приложения.

пятница, 18 декабря 2009 г.

ProcessBuilder java.io.IOException: Cannot run program : CreateProcess error=123

ProcessBuilder мутный. Он непонимает команду одной строчкой.



Такую строчку он не поймёт - CreateProcess error=123







 String debugCmd = "C:\\development\\Java\\jdk1.6.0_12\\bin\\java -cp C:\\work\\trunk\\Server\\lib\\xxx.jar; xxx.Test";

а такую совсем не поймёт - CreateProcess error=2


String debugCmd = "java -cp C:\\work\\trunk\\Server\\lib\\xxx.jar; xxx.Test";

а так поймёт!
String[] debugCmd = new String[]{
    "java", "-cp", "C:\\work\\trunk\\Server\\lib\\xxx.jar;", "xxx.Test"
  };


и поехали
ProcessBuilder processBuilder = new ProcessBuilder(debugCmd);
            processBuilder.directory(new File(home));
            processBuilder.redirectErrorStream(true);
            Process process = processBuilder.start();


узнал тут :
http://forums.sun.com/thread.jspa?threadID=5396595&messageID=10761026

четверг, 26 ноября 2009 г.

SymmetricDS UDF Firebird fuck


Invalid token.
invalid request BLR at offset 63.
function SYM_ESCAPE is not defined.
module name or entrypoint could not be found.

Хня похоже не зависит от системы(винды) - вообще непонятно от чего она зависит. Одинаково хорошо проявлялась на windows server 2003(32), 2008(32/64) с Firebird(2.1.3, 2.0.5). Возникает потому что udf  SYM_UDF.dll не всасывается. Для того чтобы всосалась необходимо пересобрать эту udf в VisualStudio под Runtime 8.0.

понедельник, 16 ноября 2009 г.

OSGI ant bnd fuck

bnd
это такая jar ка
 http://www.aqute.biz/Code/Download

Зачем bnd?
Умеет делать красивый манифест с импортами и экспортами по спецификации OSGI и jar.

Нада bnd?
Вообще нет. Основная фишка что он автоматически умеет вписывать пэкэджи в манифест.

Как bnd?
Тулза используется в ряде фрэймворков для генерации jar под OSGI. В анте она работает так -
лезит в спец файл(обычно он имеет расширение .bnd) и получает оттуда пути всех используемых в билде jar и маски импортов-экспортов, на основе чего генерит манифест и jar.

вторник, 20 октября 2009 г.

Java Service Wrapper

Он клёвый и простой.
Можно указывать зависимости от других сервисов. Куча настроек.
Таймауты на запуск/перезапуск и тп.

Как внедрять:

1)Пускач должен наследоваться от 
implements WrapperListener


четверг, 15 октября 2009 г.

Репликация с SymmetricDS

С первого взгляда всё просто, но потом появляются всякие левые ошибки, частично связанные с таймаутами(необходимо неопределённое время на запуск сервера репликации), частично хрен знает с чем.  Все примеры есть во вражеском коде - там типа скрипты, в документации описана последовательность действий для тестов(см глава 2) Вот пример на яве: