• Автоматическая закачка файла?

    @bromzh
    Drugs-driven development
    Если у тебя линукс или что-то похожее, то достаточно обычного баша:
    #!/bin/sh
    now="$(date +'%Y-%m-%d')"
    url="http://example.com/$now/$now.mp4"
    wget -c -P /папка/куда/сохранять/ $url

    И засунуть это в ежедневный крон.

    Опции wget посмотри, там куча разных штук, типа повтора при ошибке, выкачивании каталога/всего сайта, и т.д.
    Ответ написан
    Комментировать
  • Как правильно работать с чекбоксами в angular?

    @bromzh
    Drugs-driven development
    Комментировать
  • Как правильно искать элемент в List?

    @bromzh
    Drugs-driven development
    Надо вопросы чётче формулировать. Так как нифига не понятно, как у тебя устроены классы. Нет такого типа T, этой буквой обычно обозначают параметризированный тип.
    Если надо просто узнать есть объект или нет, то никакой параметризации не требуется:

    public class Foo {
    
        static List<Object> list = new LinkedList<>();
    
        public static boolean hasElem(Object elem) {
            for (Object item : list) {
                if (Objects.equals(item, elem)) {
                    return true;
                }
            }
            return false;
        }
    
        public static void main(String[] args) {
    
            list.add(1);
            list.add("s1");
            list.add(2);
            list.add("s2");
            list.add(3);
            list.add("s3");
    
            if (hasElem(3)) {
                System.out.println("Has elem 3");
            }
            if (hasElem("s2")) {
                System.out.println("Has elem \"s2\"");
            }
            if (hasElem('c')) {
                System.out.println("Has elem 'c'");
            }
        }
    }


    Если же типом T ты параметризуешь свой класс/метод, то ничего проверять не надо: когда ты создашь экземпляр такого класса, параметризованный типом String, то и список будет только из строк и поиск будет по строкам. Когда параметризуешь его Integer, то везде будут числа.
    Ответ написан
  • С чего начать изучение Java?

    @bromzh
    Drugs-driven development
    Horstmann "Core Java" 7 edition (или какое сейчас самое свежее). Ну и гуглом научись пользоваться.
    Ответ написан
    Комментировать
  • Почему все хотят django?

    @bromzh
    Drugs-driven development
    1. Для джанги есть куча готовых батареек. Для типовых проектов вообще может получиться так, что своего кода будет минимум. а весь проект - использование нужных модулей.
    2. Чёткая структура проекта, новичку не надо будет изучать структуру, как в случае с тем же фласком
    3. Все компоненты джанги (ORM, шаблонизатор, админка) поддерживаются одной командой, меньше будет случаев, когда что-то отваливается из-за несовместимости версий

    Хотя я и сам выбрал бы фласк.
    Ответ написан
    2 комментария
  • RestFul на python,какой framework выбрать?

    @bromzh
    Drugs-driven development
    API - Flask (или Eve)
    Чат - торнадо
    Ответ написан
    Комментировать
  • Как правильно организовать приведение типов при работе с generic стеком?

    @bromzh
    Drugs-driven development
    В рантайме твой параметризированный тип заменяется на Object. Последний код окажется просто бессмысленным. Ещё и instanceof.
    Тип приводи в момент получения:
    MyClass a = (MyClass) stack.pop();
    Ответ написан
    Комментировать
  • Как исправить ситуацию, когда GlassFish не обрабатывает JSF-страницы?

    @bromzh
    Drugs-driven development
    <!-- JSF mapping -->
        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <!-- Map these files with JSF -->
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.xhtml</url-pattern>
        </servlet-mapping>

    Добавь это в web.xml
    Ответ написан
    Комментировать
  • Взаимозаменяем ли switch с if в JavaScript?

    @bromzh
    Drugs-driven development
    switch - это частный случай if-else (т.е. свитч можно на иф заменить, а обратно не всегда)
    В питоне, например, свитча нет вообще, и отсутствие его не замечается.
    Ответ написан
    1 комментарий
  • Что такое/чем отличаются Repository и Dao интерфейсы?

    @bromzh
    Drugs-driven development
    Вот тутор от оракла, там всё поясняют. И ещё вот, например.
    А вообще, с названиями классов в яве всегда были разногласия и путаницы. И часто DAO называют то, что им не должно являться.

    По смыслу, DAO - довольно низкоуровневая штука, работает напрямую с хранилищем. Для каждого Transfer Object'а (сущности) должна быть реализация DAO для конкретного хранилища.
    Например, есть 2 сущности: User и Post. Есть разные хранилища: 2 SQL базы данных (MySql и Postgres), файловая система, хранилище на основе xml-файлов.
    Для объекта User есть интерфейс UserDao с методами CRUD. И должны быть 4 реализации этого метода: MySqlUserDao, PostgresUserDao, FileSystemStorageUserDao, XmlFileStorageUserDao. Аналогично для второй сущности. И обычно создаётся фабрика DAO, которая будет выдавать нужную реализацию (по первой ссылке есть схемы). Ну и в силу похожести реализаций, DAO обычно делают абстрактным и типизированным.
    Таким образом, получается унифицированный интерфейс для манипуляции данными. Можно прозрачно сменить хранилище просто выбрав другую реализацию DAO (например, через внедрение зависимостей или конфигов), не меняя бизнес-логику.

    Так что обычно DAO создают там, где нет готовой реализации связи с каким-нибудь хранилищем (или эта реализация не устраивает). А те же транкзакции - это более высокий уровень, в DAO их можно не включать, чтобы не усложнять архитектуру и монолитность.

    Репозиторий же - это более общая и абстрактная штука.
    Вообще, название "репозиторий" обычно встречается в мире спринга, в JavaEE другие термины. Да и суффикс DAO в спринге используется чаще, хотя по смыслу, это не всегда то самое DAO, в толковании Sun/Oracle.
    Ответ написан
    2 комментария
  • Где хранить "кусочки" кода?

    @bromzh
    Drugs-driven development
    Копирую в сублайм в новую вкладку. Если её не закрывать, код остаётся после выхода.
    Ответ написан
    Комментировать
  • Чем плох ajax чат?

    @bromzh
    Drugs-driven development
    Подумай, как в случае с AJAX сервер будет отдавать сообщения.
    В случае с websocket всё просто: список подключённых пользователей известен. Подключился новый пользователь, на сервере вызвался callback, соединение создалось и добавилось в список всех соединений. При получении сообщения от клиента сервер просто пройдёт в цикле по этому списку соединений, отправит данные и забудет про них. Пользователь отключился, вызвался callback, соединение удалилось из списка на сервере.

    А как в случае AJAX? Сервер не знает, сколько пользователей активно в данный момент. Клиент отправил запрос, создалось соединение, запрос пришёл на сервер, сервер ответил на него, соединение разорвалось. Если юзер уйдёт с сайта, то сервер просто не будет получать запросы. Как он определит, ушёл ли юзер или просто таймаут ещё не сработал? Можно, конечно, на сервере хранить список с пользователями, которые что-то прислали и раз в N секунд выкидывать протухших. Но это дополнительная нагрузка на серв, который и так будет нагружен огромным количеством периодических запросов (выгоднее держать 1000 открытых соединений, чем раз в секунду открывать и закрывать по тысячи соединений).
    Вот тебе ещё простой пример: есть 3 пользователя. Один ничего не пишет и каждые 3 секунды отправляет запрос на получение сообщений. 2 других каждые полсекунды отправляют сообщения. Сервер может только догадываться, в сети ли необщительный юзер, или у него таймаут не вышел. А до тех пор, он хранит все сообщения от 2-го и 3-го пользователей. Но они уже получили сообщения друг от друга, поэтому надо где-то хранить инфу для каждого пользователя, какие сообщения он уже получал, а какие - нет. Можно, конечно, и сообщения хранить только некоторое время, и отправлять на клиент всё, что есть, а уже на клиенте пропускать дубликаты. Но это, опять же, доп. нагрузка на сервер и клиент.

    В итоге, надо придумать довольно сложную логику хранения информации, которую надо отправить пользователям, да и список самих пользователей как-то хранить и мониторить. В итоге, куча малких запросов. которые будут просаживать сервер и нетривиальная система оповещений, которая, скорее всего, будет часто выдавать ошибки.
    Ответ написан
    5 комментариев
  • Как происходит связь моделей с бд в java/scala приложениях?

    @bromzh
    Drugs-driven development
    В мире Java есть много способов организации связи с БД и связи моделей с БД в частности. Есть стандарт - JPA. В мире spring есть слой совместимости с JPA, есть и иные решения. В Scala можно использовать и вышеупомянутые решения, и свои (тут уже зависит от используемого фреймворка).

    Опишу, как это устроено в JPA.

    Сперва ты описываешь связь всего приложения с БД в файле persistence.xml. В нём ты описываешь persistence-unit'ы - единицы персистентности, связь моделей с БД. Грубо говоря, можно использовать как локальные ресурсы (RESOURCE_LOCAL - связь происходит не через сервер приложений, а сторонними усилиями, связь описывается в xml-файле), так и ресурсы JTA (соединение настраивается на сервере, в приложении ты по имени получаешь нужный DataSource).

    Потом ты создаёшь классы сущностей. Создаёшь обычный (POJO) класс с аннотацией Entity, описываешь поля, геттеры и сеттеры. Аннотациями можно настраивать всякие штуки: имя таблицы в БД, имя поля, задавать связи, тип получения (LAZY/EAGER), каскадность, автогенерацию первичных ключей и т.д.

    Затем надо создать класс, который будет предоставлять интерфейс для работы с сущностями. Обычно, для каждой сущности надо сделать свой класс. Есть несколько вариантов реализации и названия этих классов. NetBeans, например, создаёт классы-фасады: один абстрактный и по-одному фасаду, наследующий абстрактный, на каждую сущность. По ссылке всё наглядно, я думаю. Каждый фасад - это бин (аннотация Stateless). В него инжектится EntityManager:
    @PersistenceContext(unitName = "AffableBeanPU")
    private EntityManager em;

    При настроенной связи с БД (в persistence.xml) в em будет нужная реализация этого менеджера, через который и происходит вся магия. Плюсом является то, что все запросы автоматом используют транкзакции.

    Ну а потом, в коде, надо просто инжектить этот фасад через аннотацию EJB и использовать его (например, для реализации REST API):
    import org.foo.example.entities.Foo;
    import org.foo.example.facades.FooFacade;
    
    @Path("foo")
    @Consumes({"application/json", "application/xml"})
    @Produces({"application/json", "application/xml"})
    class FooResource {
    
        @EJB
        FooFacade facade;
    
        @GET
        public List<Foo> getAll() {
            return facade.findAll();
        }
    
        @POST
        public Foo create(Foo item) {
            facade.create(item);
            return item;
        }
    
        @GET
        @Path("{id}")
        public Foo getOne(@PathParam("id") Integer id) {
            return facade.find(id);
        }
    
        @PUT
        @Path("{id}")
        public Foo update(@PathParam("id") Integer id, Foo item) {
            item.setId(id);
            facade.update(item);
            return item;
        }
    
        @DELETE
        @Path("{id}")
        public void delete(@PathParam("id") Integer id) {
            facade.remove(facade.find(id));
        }    
    }


    UPD.
    Запилил демо-приложение, можешь взять посмотреть.

    Суть такая: ставим wildfly, добавляем пользователя. Запускаем сервер. Можно зайти в админку 127.0.0.1:9990
    Там на вкладке Configuration->Datasources будет 1 источник данных - ExampleDS. Это h2 - встроенная БД, которая крутится в данном случае в оперативке и при перезапуске сервера сбрасывается.

    В файле persistence.xml настраиваем ресурсы: указываем имя persistence-unit, и его тип - JTA. Таким образом, ничего локально настраивать не надо, приложение получает всё через ресурс, который настроен на самом сервере, по его имени (java:jboss/datasources/ExampleDS). Единственное, в конфиге указываем
    <property name="hibernate.hbm2ddl.auto" value="update" />
    чтобы таблицы в БД автоматом создавались (если их нет).

    В пакете entities лежат 2 сущности: User и Post. Обе аннотированны Entity, таким образом, JPA может с ними работать. Ещё в сущностях присутствуют аннотации для валидации сущностей (это всякие NotNull, Size, Min, Valid и т.д.). Так же, там есть простая двусторонняя связь. В сущности Post есть связь ManyToOne к сущности User, в сущности User есть связь OneToMany со списком постов пользователя. Последняя связь нужна, чтобы обеспечить каскадность на уровне JPA, но геттеров/сеттеров на неё нет, потому что я не хочу, чтобы этот список вылезал при получении пользователя. По-хорошему, надо её убрать, а в таблице post (которая связана с сущностью Post) надо самому прописать каскадность при удалении, потому что пользователь особо не должен знать, что у него в зависимых.

    Далее, в пакете dao находятся классы для доступа к сущностям.
    AbstractDao - это абстрактный generic-класс, в котором описаны операции для управления хранением сущностей. Все методы там тривиальны, за исключением получения.

    Вообще, есть несколько способов получить сущность. Можно использовать простые SQL-запросы, можно указывать именованные запросы (NamedQuery), которые можно описать либо через одноимённую аннотацию, либо в коде. Вторые имеют бонус в виде типобезопасности.
    И ещё один из вариантов - это динамические запросы через CriteriaBuilder. JPA генерирует метаклассы для классов, отмеченных аннотацией Entity. Запросы можно строить, в том числе, используя эти метаклассы. Большим плюсом является то, что такие запросы можно (и нужно) делать типобезопасными (CriteriaQuery, TypedQuery). И IDE не ругается на приведение типов, которое было бы в случае простых нетипизированных запросов. Вообще, по этой ссылке есть подробное описание таких типобезопасных запросов.

    Особое внимание к методам findWithLazy и findAllWithLazy. В сущности Post поле owner помечено как связь ManyToOne с ленивым типом получения (fetch = FetchType.LAZY). Просто так такое поле получить трудно: ленивая загрузка работает только в пределах сессии: создалась сессия, запросились данные, сессия закрылась. И ленивые поля по-умолчанию не добавляются к возвращаемому объекту. Есть несколько способов побороть это. Можно убрать ленивость (fetch = FetchType.EAGER). Можно вызвать метод size() для поля-коллекции. Можно вручную получать поля. У меня сделано именно так. В методы findWithLazy и findAllWithLazy передаётся список полей, необходимых для получения. Я создаю запрос на получение корневого элемента: Root<T> root = criteriaQuery.from(entityClass);, а затем в цикле получаю необходимые поля: for (String field : fields) { root.fetch(field); }. При выполнении запроса эти поля присоединятся к результату.

    В классах UserDao и PostDao я указываю аннотацию Stateless для CDI и реализую абстрактный метод getEntityManager() для получения экземпляра PersistenceManager. Сам экземпляр я внедряю через аннотацию PersistenceContext, где в качестве параметра unitName я указываю имя persistence-unit, которое обозначил в persistence.xml.

    Ну и наконец, использование классов DAO в приложении (пакет resources). Я создаю простой REST API с помощью JAX-RS. Для каждой сущности создаю по своему ресурсу, в который внедряю через аннотацию EJB нужный DAO-класс. Там, думаю, всё очевидно.

    В описании репозитория указано, как запустить и потестить всё это дело.

    Надеюсь, всё понятно.
    Ответ написан
    4 комментария
  • Как быстро переучиться с Python на Java?

    @bromzh
    Drugs-driven development
    Прочитай для начала книгу Хорстманн К., Корнелл Г. - Java. Библиотека профессионала. Там основы языка. Потом бери книгу для разработки под android и пиши.

    Можно ли писать приложения на Java прям на своем девайсе?
    Сложно. Посмотри https://codenvy.com - бесплатная облачная IDE для явы. Под андроид там вроде можно писать, хотя хз насколько будет удобно это на планшете юзать. Вот скрины:
    ce5e378ff0a94e6092892b302b1367f0.png33a31a42d0ee427d91b4031681081968.png
    Ответ написан
    Комментировать
  • Как скрыть WAR от глаз?

    @bromzh
    Drugs-driven development
    Так jboss (который сейчас wildfly), да и вообще, почти все appserver'а, в любом случае разархивируют содержимое jar/ear к себе. Хороший способ скрыть всё это - встроить сервер в jar (jetty прекрасно интегрируется, всё запускается из простого jar, в который можно упаковать и содержимое webapp). Ещё можно прикрутить к этой штуке шифрование и загрузчик, который на лету будет распаковывать зашифрованный архив (можно даже в оперативку) и запускать приложуху. Достать .class-файлы и содержимое webapp всё ещё можно, но уже труднее.
    Ответ написан
    Комментировать
  • Что быстрее, обновление информации в БД или удаление и запись?

    @bromzh
    Drugs-driven development
    На самом деле, тут некая неоднозначность. Вот тут описана проблема и возможные пути её решения. В двух словах: всё ограничено скоростью диска. Инсерт быстрый (50 тыщ операций в секунду), но транкзакции медленные (60 в секунду). Если вставить кучу инсертов в одну транкзакцию (через BEGIN...COMMIT) - будет быстро. Ещё можно выполнить PRAGMA synchronous=OFF, тогда sqlite не будет ждать подтверждения записи. Но в этом случае, при отключении питания, все несохранённые данные потеряются.

    Почитай ещё это:
    tech.vg.no/2011/04/04/speeding-up-sqlite-insert-op...
    dba.stackexchange.com/questions/8028/whats-better-...
    stackoverflow.com/questions/1271641/in-sql-is-upda...
    Ответ написан
    1 комментарий
  • Как правильно проверять данные при создании объекта в Java?

    @bromzh
    Drugs-driven development
    Можно проверять при создании (через конструктор/фабрику/билдер/etc). Проверять можешь через assert или через if, выбрасывая нужную ошибку (какую-нибудь IllegalArgumentException, например).
    Можешь подрубить любой удобный java validation framework. Если используешь JavaEE API, то он вроде как уже включён туда. Остаётся только выбрать реализацию (если используешь application server, то вероятнее всего, validation api включён в поставку сервера, и в мавене достаточно указать scope provided для JavaEE API). Расставь нужные аннотации и наслаждайся результатом.
    Ответ написан
    Комментировать
  • Почему Calibri на сайте отличается от макетного?

    @bromzh
    Drugs-driven development
    man "рендеринг шрифтов"
    Ответ написан
    Комментировать
  • Автоматическое преобразование и явное преобразование типов в JAVA?

    @bromzh
    Drugs-driven development
    Явное - это когда ты в скобках (либо через вызов методов) преобразуешь переменную одного типа к другому. При этом, не факт, что это преобразование пройдёт и пройдёт правильно.

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

    Пример:
    int a = 70000;
    short b = 10;
    int c = a + b; // Тут b автоматом преобразуется к типу int, так как компилятор знает, 
    // что данные из него не потеряются при преобразовании.
    short d = (short) (a + b);


    Если убрать преобразование всей суммы к short, не скомпилится, типы не совпадают. Переменную "a" (вернее, всю сумму) надо преобразовать к short, но результат суммы будет int. short меньше int и данные из "а" могут потеряться. Нужно вручную преобразовывать.

    С классами всё примерно также.
    Ответ написан
    1 комментарий