LINUX.ORG.RU

Сообщения popov-aa

 

Не применяется профиль к LXD контейнеру

Форум — Admin

Добрый день. На рабочей машине под управлением Kubuntu я настроил проброс X11 из контейнера на хост по этой статье: https://blog.simos.info/running-x11-software-in-lxd-containers/ В убунте с LXD вообще минимум головняка. Все свелось к созданию и назначению контейнеру профиля следующего содержания:

config:
  environment.DISPLAY: :0
  nvidia.driver.capabilities: all
  nvidia.runtime: "true"
  user.user-data: |
    packages:
      - x11-apps
      - mesa-utils
description: GUI LXD profile
devices:
  X0:
    bind: container
    connect: unix:@/tmp/.X11-unix/X0
    listen: unix:@/tmp/.X11-unix/X0
    security.gid: "1000"
    security.uid: "1000"
    type: proxy
  mygpu:
    type: gpu
Xauth:
    path: /home/popov-aa/.Xauthority
    source: /home/popov-aa/.Xauthority
    type: disk
name: x11
used_by: []

Решил повторить успех на домашней системе под управлением ArchLinux. Официальный гайд я выполнил частично, опустив настройку сети, но непривилегированные контейнеры настроены.

Суть проблемы сводится к тому, что под ArchLinux как будто не применяются профили.

[popov-aa@PopovDesktop ~]$ lxc profile show x11
config:
  environment.DISPLAY: :0
  nvidia.driver.capabilities: all
  nvidia.runtime: "true"
  user.user-data: |
    packages:
      - x11-apps
      - mesa-utils
description: GUI LXD profile
devices:
  X0:
    bind: container
    connect: unix:@/tmp/.X11-unix/X0
    listen: unix:@/tmp/.X11-unix/X0
    security.gid: "1000"
    security.uid: "1000"
    type: proxy
  mygpu:
    type: gpu
name: x11
used_by:
- /1.0/instances/centos7-ians
- /1.0/instances/mycontainer
- /1.0/instances/centos7-ians-test
[popov-aa@PopovDesktop ~]$ lxc config device show centos7-ians-test
{}
[popov-aa@PopovDesktop ~]$

[popov-aa@centos7-ians-test ~]$ ls /tmp/.X11-unix/X0
ls: cannot access /tmp/.X11-unix/X0: No such file or directory
[popov-aa@centos7-ians-test ~]$ glxgears 
No protocol specified
Error: couldn't open display :0
[popov-aa@centos7-ians-test ~]$

В чем может быть проблема?

 , , ,

popov-aa ()

No EntityManager with actual transaction available for current thread

Форум — Development

Имеется приложение (spring-boot, spring-data-jpa) в одном из бинов которого я хочу создать с помощью EntityManager пару сущностей. В результате получаю исключение «No EntityManager with actual transaction available for current thread - cannot reliably process ‘persist’ call» при вызове persist. Сохранение через JpaRepository при этом работает корректно. Метод, в котором происходит вызов проаннотирован @Transactional. Не подскажите, с чем это может быть связано? Репозиторий: https://github.com/popov-aa/spring-boot-test

 , , ,

popov-aa ()

yoyo migrations не может развернуть БД на mysql

Форум — Development

Столкнулся с тем, что yoyo migrations не может развернуть БД на mysql, в которой объявляются процедуры с REPEAT.

Допустим, мы хотим использовать чуть подчищенный вариат дампа произведенного с помощью mysqldump:

DROP TABLE IF EXISTS `test_table`;
CREATE TABLE `test_table` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(8) COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

DROP TABLE IF EXISTS `yoyo_lock`;
CREATE TABLE `yoyo_lock` (
  `locked` int NOT NULL DEFAULT '1',
  `ctime` timestamp NULL DEFAULT NULL,
  `pid` int NOT NULL,
  PRIMARY KEY (`locked`)
) ENGINE=InnoDB;

DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `test_function`() RETURNS int
    READS SQL DATA
    DETERMINISTIC
begin
	declare test_var int default 1;
	repeat
		set test_var = test_var + 1;
	until test_var < 10 end repeat;
	return test_var;
end ;;

CREATE DEFINER=`root`@`%` PROCEDURE `test_procedure`()
begin
	declare test_var int default 1;
	repeat
		set test_var = test_var + 1;
	until test_var < 10 end repeat;
end ;;
DELIMITER ;

Как видим, mysql его спокойно разворачивает:

[popov-aa@archlinux yoyo]$ mysql -u root -p -h 172.28.1.21 test_db < ./migrations/20200717_01_dHiTT-create-schema.sql 
Enter password: 
[popov-aa@archlinux yoyo]$ 

Теперь попробуем развернуть этот же дамп с помощью yoyo, получаем ошибку:

DROP TABLE IF EXISTS `test_table`;
CREATE TABLE `test_table` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(8) COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

DROP TABLE IF EXISTS `yoyo_lock`;
CREATE TABLE `yoyo_lock` (
  `locked` int NOT NULL DEFAULT '1',
  `ctime` timestamp NULL DEFAULT NULL,
  `pid` int NOT NULL,
  PRIMARY KEY (`locked`)
) ENGINE=InnoDB;

CREATE DEFINER=`root`@`%` FUNCTION `test_function`() RETURNS int
    READS SQL DATA
    DETERMINISTIC
begin
	declare test_var int default 1;
	repeat
		set test_var = test_var + 1;
	until test_var < 10 end repeat;
	return test_var;
end ;

CREATE DEFINER=`root`@`%` PROCEDURE `test_procedure`()
begin
	declare test_var int default 1;
	repeat
		set test_var = test_var + 1;
	until test_var < 10 end repeat;
end ;
Получаем:
[popov-aa@archlinux yoyo]$ yoyo apply
/home/popov-aa/.local/lib/python3.8/site-packages/pymysql/cursors.py:170: Warning: (1051, "Unknown table 'test_db.test_table'")
  result = self._query(query)
Traceback (most recent call last):
...
pymysql.err.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DELIMITER' at line 1")
[popov-aa@archlinux yoyo]$ 
Модифицируем дамп, удалив DELIMITER:
[popov-aa@archlinux yoyo]$ yoyo apply
Traceback (most recent call last):
...
pymysql.err.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 8")
[popov-aa@archlinux yoyo]$ 
При этом вариант без REPEAT проходит на ура:
DROP TABLE IF EXISTS `test_table`;
CREATE TABLE `test_table` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(8) COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

DROP TABLE IF EXISTS `yoyo_lock`;
CREATE TABLE `yoyo_lock` (
  `locked` int NOT NULL DEFAULT '1',
  `ctime` timestamp NULL DEFAULT NULL,
  `pid` int NOT NULL,
  PRIMARY KEY (`locked`)
) ENGINE=InnoDB;

CREATE DEFINER=`root`@`%` FUNCTION `test_function`() RETURNS int
    READS SQL DATA
    DETERMINISTIC
begin
	declare test_var int default 1;
	return test_var;
end ;

CREATE DEFINER=`root`@`%` PROCEDURE `test_procedure`()
begin
	declare test_var int default 1;
end ;
[popov-aa@archlinux yoyo]$ yoyo apply
[popov-aa@archlinux yoyo]$ 
У кого-нибудь есть догадки в чем проблема и как быть?

 ,

popov-aa ()

Проблемы с checkinstall под Ubuntu 20.04

Форум — Admin

Пытаюсь собрать пакет qamqp с помощью checkinstall под Ubuntu 20.04. Беру исходники с github.com, выполняю qmake, make - никаких ошибок. На sudo checkinstall возникает следующая ошибка:

========================= Результаты установки ===========================
cd src/ && ( test -e Makefile || /usr/lib/qt5/bin/qmake -o Makefile /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/src.pro ) && make -f Makefile install
make[1]: вход в каталог «/home/popov/Mountpoints/SSD/Projects/C++/qamqp/src»
/usr/lib/qt5/bin/qmake -install qinstall /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpauthenticator.h /usr/include/qamqp/qamqpauthenticator.h
Error copying /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpauthenticator.h to /usr/include/qamqp/qamqpauthenticator.h: Cannot create /usr/include/qamqp/qamqpauthenticator.h for output
make[1]: [Makefile:603: install_headers] Ошибка 3 (игнорирование)
/usr/lib/qt5/bin/qmake -install qinstall /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpchannel.h /usr/include/qamqp/qamqpchannel.h
Error copying /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpchannel.h to /usr/include/qamqp/qamqpchannel.h: Cannot create /usr/include/qamqp/qamqpchannel.h for output
make[1]: [Makefile:604: install_headers] Ошибка 3 (игнорирование)
/usr/lib/qt5/bin/qmake -install qinstall /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpclient.h /usr/include/qamqp/qamqpclient.h
Error copying /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpclient.h to /usr/include/qamqp/qamqpclient.h: Cannot create /usr/include/qamqp/qamqpclient.h for output
make[1]: [Makefile:605: install_headers] Ошибка 3 (игнорирование)
/usr/lib/qt5/bin/qmake -install qinstall /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpexchange.h /usr/include/qamqp/qamqpexchange.h
Error copying /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpexchange.h to /usr/include/qamqp/qamqpexchange.h: Cannot create /usr/include/qamqp/qamqpexchange.h for output
make[1]: [Makefile:606: install_headers] Ошибка 3 (игнорирование)
/usr/lib/qt5/bin/qmake -install qinstall /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpglobal.h /usr/include/qamqp/qamqpglobal.h
Error copying /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpglobal.h to /usr/include/qamqp/qamqpglobal.h: Cannot create /usr/include/qamqp/qamqpglobal.h for output
make[1]: [Makefile:607: install_headers] Ошибка 3 (игнорирование)
/usr/lib/qt5/bin/qmake -install qinstall /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpmessage.h /usr/include/qamqp/qamqpmessage.h
Error copying /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpmessage.h to /usr/include/qamqp/qamqpmessage.h: Cannot create /usr/include/qamqp/qamqpmessage.h for output
make[1]: [Makefile:608: install_headers] Ошибка 3 (игнорирование)
/usr/lib/qt5/bin/qmake -install qinstall /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpqueue.h /usr/include/qamqp/qamqpqueue.h
Error copying /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqpqueue.h to /usr/include/qamqp/qamqpqueue.h: Cannot create /usr/include/qamqp/qamqpqueue.h for output
make[1]: [Makefile:609: install_headers] Ошибка 3 (игнорирование)
/usr/lib/qt5/bin/qmake -install qinstall /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqptable.h /usr/include/qamqp/qamqptable.h
Error copying /home/popov/Mountpoints/SSD/Projects/C++/qamqp/src/qamqptable.h to /usr/include/qamqp/qamqptable.h: Cannot create /usr/include/qamqp/qamqptable.h for output
make[1]: [Makefile:610: install_headers] Ошибка 3 (игнорирование)
/usr/lib/qt5/bin/qmake -install qinstall -exe libqamqp.so.0.5.0 /usr/lib/libqamqp.so.0.5.0
Error copying libqamqp.so.0.5.0 to /usr/lib/libqamqp.so.0.5.0: Cannot create /usr/lib/libqamqp.so.0.5.0 for output
make[1]: [Makefile:626: install_target] Ошибка 3 (игнорирование)
strip --strip-unneeded /usr/lib/libqamqp.so.0.5.0
strip: «/usr/lib/libqamqp.so.0.5.0»: Нет такого файла
make[1]: [Makefile:627: install_target] Ошибка 1 (игнорирование)
ln -f -s libqamqp.so.0.5.0 /usr/lib/libqamqp.so
ln -f -s libqamqp.so.0.5.0 /usr/lib/libqamqp.so.0
ln -f -s libqamqp.so.0.5.0 /usr/lib/libqamqp.so.0.5

При этом пакет собирается, но содержит далеко не все инсталлируемые файлы. Первое что бросается в глаза - отсутствие бинарников. Кто-нибудь сталкивался с подобным? Убунта дефолтная, сразу после установки. Полный вывод: https://pastebin.com/hZG6LATr

 ,

popov-aa ()

Резервирование docker

Форум — Development

Добрый день, товарищи. На боевом сервере, что мне доверили, в docker-контейнерах крутится следующее: postgres, nginx, gitea, certbot, youtrack, registry, portainer и корпоративное приложение на java. Все контейнеры описаны в docker-compose, а все тома именованные. Насколько неправилен следующий алгоритм бэкапа:

  • Останавливаю docker, чтобы не велась запись в тома;
  • Тарболю /var/lib/docker/volumes/ вместе с docker-compose.yaml;
  • Запускаю docker;
  • Заливаю полученный тарбол на резервный сервер. В случае уничтожения основного сервера на резервном распаковываю в /var/lib/docker/volumes тома, запускаю docker-compose up. Насколько описанный способ самодостаточен, охватывает ли он все нюансы? Как я понимаю, вопрос резервирования в докере можно разбить на три части: резервирование образов, резервирование контейнеров и резервирование томов и все это можно делать встроенным средствами docker. Но резервировать образы я не вижу смысла, так как все они есть в docker hub. Смысл резервировать контейнеры тоже не ясен, так как я использую именованные тома и бэкаплю их. Бэкап томов средствами докера выглядит сложнее, чем банальный тарбол.

 

popov-aa ()

Однажды установленное jsonb поле не удается изменить

Форум — Development

Имеется вебприложение на следующем стеке: backend: java 8, spring-boot, spring-mvc, hibernate, postgresql. frontend: reactjs, material-ui.

Возникла необходимость отображать яндекс-карту с метками. Я решил сохранять информацию, которую получаю от яндексовского сервиса в jsonb.

Сущность в которой необходимо сохранять инфу:

@NoArgsConstructor
@Getter @Setter
@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
@Entity
public class Location extends Identifiable implements Serializable {
    @Type(type = "jsonb")
    @Column(columnDefinition = "jsonb")
    private Geolocation geolocation;
}
https://pastebin.com/FX9XUxjg

Классы, являющиеся отражением структуры json:

@NoArgsConstructor
@Getter @Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@TypeDefs({
        @TypeDef(name = "json", typeClass = JsonStringType.class),
        @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
@MappedSuperclass
public class Geolocation {
    private Double latitude;
    private Double longitude;
    private Address address;
}
https://pastebin.com/dqDTeddD

@NoArgsConstructor
@Getter
@Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@TypeDefs({
        @TypeDef(name = "json", typeClass = JsonStringType.class),
        @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
@MappedSuperclass
public class Address {
    private String countryCode;
    private String formatted;
    private String postalCode;
    private Map<String,String> components = new HashMap<>();
}

https://pastebin.com/3pVBBGGH

Метод контроллера, вызывающийся для сохранения геолокации:

@Log4j2
@Controller
@RequestMapping(value = "/api/locations")
public class LocationController {

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private LocationRepository locationRepository;

    @PreAuthorize("hasRole('ADMIN')")
    @Transactional
    @RequestMapping(value = "/{id}/geolocation", method = RequestMethod.POST)
    @ResponseBody
    public com.helan.videoafisha.dto.general.Location saveGeolocation(
            @PathVariable("id") Long id,
            @RequestBody com.helan.videoafisha.dto.backend.frontend.reactjs.locations.with_geolocation.Geolocation modelGeolocation) {
        Location location = locationRepository.getOne(id);
        Geolocation geolocation = modelMapper.map(modelGeolocation, Geolocation.class);
        location.setGeolocation(geolocation);
        locationRepository.save(location);
        return modelMapper.map(location, com.helan.videoafisha.dto.general.Location.class);
    }
}
https://pastebin.com/BbxWxpNH

Суть проблемы заключается в том, что когда geolocation равен null, тогда даный метод отрабатывает корректно: https://imgur.com/PE5lvKQ.png

Hibernate: 
    update
        backend.location 
    set
        geolocation=?,
        max_device_count=?,
        site_id=?,
        time_zone_id=?,
        title=? 
    where
        id=?
2020-04-01 16:42:31.339 DEBUG - c.h.v.b.m.l.LogRequestFilter             : 200 POST /api/locations/1/geolocation [member #1/admin@mail.ru] 127.0.0.1:41090 {"isRequesting":false,"latitude":55.69962195079022,"longitude":37.62218505859374,"address":{"countryCode":"RU","formatted":"Россия, Москва, Варшавское шоссе, 13с4","postalCode":"117105","components":{"country":"Россия","province":"Центральный федеральный округ","locality":"Москва","street":"Варшавское шоссе","house":"13с4"}}}
https://imgur.com/8mc7odJ.png

После этого, когда geolocation не null повторные вызовы с другими данными не приводят ни к каким изменениям. Даже update не вызывается. Отладка метода не выявила никаких иных условий выполнения.

2020-04-01 16:49:14.836 DEBUG - c.h.v.b.m.l.LogRequestFilter             : 200 POST /api/locations/1/geolocation [member #1/admin@mail.ru] 127.0.0.1:41202 {"isRequesting":false,"latitude":55.70117301801526,"longitude":37.58991271972656,"address":{"countryCode":"RU","formatted":"Россия, Москва, улица Вавилова, 9Ас17","postalCode":"117312","components":{"country":"Россия","province":"Центральный федеральный округ","locality":"Москва","street":"улица Вавилова","house":"9Ас17"}}}

Чем может быть вызвано подобное поведение? Если вручную установить колонку geolocation в null, то метод отработает как надо.

 , , , ,

popov-aa ()

nested containers в boost-di

Форум — Development

В целях изучения Hypodermic перевел свой старый проект на Hypodermic. Всё было прекрасно, пока я не столкнулся с невозможностью использовать forward declaration для зависимостей, инжектируемых через конструктор для классов, порождаемых с помощью resolve.

Однако почти весь проект уже переведен на использование инъекций зависимостей и автосвязывания и не хотелось от этого отказываться.

Лишен ли этого недостатка boost-di? Если да, то подскажите как в нем реализовать аналог nested containers из Hypodermic и как получить в качестве зависимости контейнер, дабы вручную извлечь из него требуемую зависимость?

 

popov-aa ()

Рабочие столы в Gnome (Ubuntu 19)

Форум — Desktop

После многих лет использования ArchLinux решил попробовать Ubuntu (19), и в качестве десктопа он мне очень даже понравился. Одна беда: рабочие столы почему-то расположены вертикально, а не горизонтально, как я привык и с хоткеями беда.

Большая часть расширений не работает, запустился только «Workspace Matrix», он смог разместить рабочие столы горизонтально. Но он не предоставляет возможности настроить хоткеи для переключения, а в стандартных настройках хоткеев доступно переключение рабочих столов только по вертикали.

Ctrl+Alt+Left/Right в продуктах JetBrains не работает, ибо захардкожено на управление рабочими столами. Помогите решить данные проблемы.

Резюмирую, что мне нужно: 1) Чтобы рабочих столов было 4 по горизонтали; 2) Чтобы переключаться между ними можно было по Alt+A (предыдущий), Alt+D (следующий) с враппингом; 3) Чтобы в Idea и Webstorm работали хоткеи Alt+Ctrl+Left/Right.

 

popov-aa ()

Ошибка в тесте geekbrains?

Форум — Talks

Пришла пора менять работу. Решил попроходить различные тесты, чтобы выявить пробелы в знаниях и устранить их. Попутно заинтересовался курсами в geekbrains, потому их тесты стал проходить первыми.

Вопрос из группы сложных: https://i.imgur.com/KOMTtok.png

Так как цикл do-while, первая итерация у нас безусловная, напечатали звездочку, результат целочисленного деления сохранили в i = 1. Выполняем проверку условия - результат целочисленного деления 1/2 (с отбрасыванием дробной части) - 0. Выходим из цикла. Вроде бы все просто, отвечаю «одну». В конце теста узнаю, что этот ответ мне не засчитали.

Компилирую этот код gcc (linux,x86_64), результат получаю тот же - одна звезда:

[popov@PopovIansWorkstation ~]$ cat test1.cpp 
#include <iostream>
int main(int argc, char **argv) {
  int i = 5;
  do {
    std::cout << '*';
    i /= 4;
  } while (i/2);
  std::cout << std::endl;
  return 0;
}
[popov@PopovIansWorkstation ~]$ g++ test1.cpp && ./a.out 
*
[popov@PopovIansWorkstation ~]$ 
Ошибка в тесте, подумал я и написал об этом в geekbrains. Специалист, с которым я связался, уточнил этот вопрос у ответственного лица, и ответил мне, что верный ответ «две звезды». Я не стал настаивать на своей правоте, вдруг в этом примитивном коде я упустил что-то важное. Потому хочу обсудить этот вопрос с вами.

 , ,

popov-aa ()

Реакция фронтенда на изменения данных на сервере при оповещении через websocket

Форум — Development

Имеется бэкенд на springboot. Работа с БД осуществляется посредством spring-data-jpa. Еще есть фронтенд на vuejs.

Захотелось мне реализовать обновление страницы при изменении данных на сервере, для чего я завел websocket (sockjs, stomp). Вебсокет планирую пока использовать только для оповещения сервером всех заинтересованных об изменении данных.

Вопрос первый, об организации каналов оповещения. Допустим у меня есть четыре сущности: A, B, C, D. Еще есть три компонента:

  • cAB, его состояние зависит от сущностей A и B
  • cCD, его состояние зависит от сущностей C и D
  • cABC, его состояние зависит от сущностей A, B и C

Сущности могут изменяться на сервере в рамках одной транзакции в различных комбинациях. Хотелось бы минимизировать число обновлений компонентов при изменении данных на сервере.

Допустим вызов одного ресурса производит изменение сущностей A, B, C. В итоге я хотел бы чтобы в результате все три компонента обновились по одному разу.

Вариант первый: создать по каналу на сущность и при изменении каждой сущности постить в соответствующий ей канал сообщение. Каждый компонент подписывается на каналы сущностей, от которых зависит его состояние. Но тогда компонент cAB обновится два раза, первый раз по сообщению от канала A, второй раз по изменению по сообщению канала B. Решить эту проблему можно заведя таймер, который сбрасывался бы получив каждое сообщение. По таймауту происходило бы обновление. Таким образом следующие друг за другом сообщения приводили бы к одному единственному обновлению. Но тут надо во vuejs реализовывать эту логику на таймерах. И вообще нормальные ли это решение?

Вариант второй: сообщение об обновлении постилось бы в один единственный канал, сообщение содержало бы список сущностей, которые изменились. Минус один и существенный на мой взгляд: любой клиент получал бы сообщения об обновлении сущностей, которые ему даже не интересы в этот момент. А у меня есть сущности, которые обновляются раз в 5 секунд.

Какие есть более оптимальные варианты на ваш взгляд?

Вопрос второй. Так как клиенты не будут слать серверу никаких сообщений по вебсокету, аннотации @MessageMapping @SendTo для меня бесполезны, ибо отправка сообщений будет происходить из контроллеров rest посредством вызова SimpMessagingTemplate.this.template.convertAndSend Но транзакция закрывается при выходе из транзакционного метода. Получается даже если я вызываю convertAndSend в конце метода контроллера, данные еще не зафиксированы, а я уже шлю сообщение клиентам. Каким образом организовать отправку сообщения клиентам после успешной фиксации транзакции? Этот вопрос может быть связан со следующим.

Если подход с отправкой сообщения об изменении сущностей в канал соответствующий этой сущности является оптимальным, то я хотел автоматизировать отправку сообщений, чтобы в каждом методе контроллеров не приходилось вести учет сущностей, который я меняю. В голову пришла такая мысль: обрабатывать фиксацию транзакций, в каждом событии анализировать сущности, которые были повержены изменению, постить в каналы соответствующие этим сущностям сообщения. Это возможно технически? Отследить успешный коммит транзакции и перебрать измененные сущности в этой транзакции? И насколько кошерен этот подход?

Еще есть вариант, создавать на каждый компонент свой канал, и чтобы сервер при изменении сущностей постил сообщения в каналы компонентов, которые зависят от этих сущностей. Но для этого на сервере нужно поддерживать список компонентов с зависимостями от сущностей. Мне кажется это совсем фу.

Буду рад любым комментариям и советам.

 , , , ,

popov-aa ()

Занять свободное пространство в bootstrap

Форум — Web-development

Имеется кусок код вида:

<div class="container-fluid p-4">
    <h3 class="mb-4"><b-breadcrumb :items="pagePath"/></h3>
    <div class="row">
        <device-types-component class="h-auto mb-4 mr-4"/>
        <android-client-update-channels-component class="h-auto mb-4 w-auto"/>
    </div>
</div>

Выглядит это вот так.

Вопрос первый: как сделать так, чтобы один из блоков занимал всю оставшуюся ширину? Вопрос второй: как сделать так, чтобы оба блока занимали всю оставшуюся ширину? Вопрос третий: как сделать так, чтобы блоки занимали всю оставшуюся доступную высоту?

Извиняюсь заранее за нубские вопросы. Я в вебе не силен.

 , ,

popov-aa ()

Каскадное удаление связных сущностей

Форум — Development

У меня есть несколько связных сущностей:

@NoArgsConstructor
@Getter @Setter
@Entity
public class Organization extends AbstractIdentifiable {

    @Column(nullable = false, unique = true)
    @NotBlank
    private String title;

    @ManyToOne(optional = false)
    @JoinColumn(nullable = false)
    private Member registrationMember;

    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Calendar registrationDateTime;

    @OneToOne(mappedBy = "organization", cascade = CascadeType.ALL)
    private Site site;

    @OneToOne(mappedBy = "organization", cascade = CascadeType.ALL)
    private Advertiser advertiser;

}

@NoArgsConstructor
@Getter @Setter
@Entity
public class Advertiser extends AbstractIdentifiable {

    @OneToOne(optional = false)
    @JoinColumn(nullable = false)
    private Organization organization;

    @ManyToMany(mappedBy = "advertisers")
    private Set<Member> members = new HashSet<>();

    @OneToMany(mappedBy = "advertiser", cascade = CascadeType.ALL)
    private Set<PaidVideo> paidVideos = new HashSet<>();

}
@NoArgsConstructor
@Getter @Setter
@Entity
public class PaidVideo extends AbstractIdentifiable {

    @OneToOne(optional = false)
    @JoinColumn(nullable = false)
    private Video video;

    @ManyToOne(optional = false)
    @JoinColumn(nullable = false)
    private Advertiser advertiser;

    @OneToMany(mappedBy = "paidVideo", cascade = CascadeType.ALL)
    private Set<Booking> bookings = new HashSet<>();

}

Перечислил только те, что имеют непосредственное отношение к вопросу, от общей сущности (вверху), к зависимым (внизу).

Пытаюсь удалить сущность Organization. Ожидаю, что по каскадной операции (cascade = CascadeType.ALL) будут удалены все связные сущности: Advertiser, PaidVideo и так далее:

@Log4j2
@Controller
@RequestMapping("/api/organizations")
public class OrganizationController {

    @Autowired
    private OrganizationRepository organizationRepository;

    @PreAuthorize("hasRole('ADMIN')")
    @Transactional
    @RequestMapping(value = "/{id}/delete", method = RequestMethod.POST)
    public ResponseEntity delete(@PathVariable("id") Long id) {
        organizationRepository.deleteById(id);
        return ResponseEntity.ok().build();
    }

}

Однако этого не происходит. Hibernate выкачивает все связные сущности, а после пытается первой и единственной удалить сущность Advertiser, закономерно получая ошибку ограничения целостности: https://pastebin.com/Z0M9BdM7

Чем может быть вызвано такое поведение? Разве hibernate не должен был построить дерево зависимостей сущностей и удалять их начиная с листьев? Почему при удалении Organization происходит только попытка удаления Advertiser, игнорируя зависимые сущности Advertiser? При чем это единственная попытка удаления чего либо, она происходит при вызове метода organizationRepository.deleteById(id); и после происходит выход из транзакционного метода, и коммит транзакции. В общем, колдунство какое-то.

Граф связей таблиц в БД: https://i.imgur.com/lPixAnd.png

 , , , ,

popov-aa ()

Jackson2 && MixIn

Форум — Development

Есть две связные сущности: Organization самодостаточна, Site имеет ссылку на нее:

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
public class Site extends AbstractIdentifiable {

    @OneToOne(optional = false)
    private Organization organization;

    @ManyToMany(mappedBy = "sites", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<Member> members = new HashSet<>();

    @OneToMany(mappedBy = "site", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<Location> locations = new HashSet<>();

    public Site() {
    }

    public Organization getOrganization() {
        return organization;
    }

    public void setOrganization(Organization organization) {
        this.organization = organization;
    }

    public Set<Member> getMembers() {
        return members;
    }

    public void setMembers(Set<Member> members) {
        this.members = members;
    }

    public Set<Location> getLocations() {
        return locations;
    }

    public void setLocations(Set<Location> locations) {
        this.locations = locations;
    }

}
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

@Entity
public class Organization extends AbstractIdentifiable implements Serializable {

    @Column(nullable = false)
    @NotBlank
    private String title;

    @OneToOne(mappedBy = "organization", cascade = CascadeType.ALL)
    private Site site;

    @OneToOne(mappedBy = "organization", cascade = CascadeType.ALL)
    private Advertiser advertiser;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Site getSite() {
        return site;
    }

    public void setSite(Site site) {
        this.site = site;
    }

    public Advertiser getAdvertiser() {
        return advertiser;
    }

    public void setAdvertiser(Advertiser advertiser) {
        this.advertiser = advertiser;
    }

}

Когда я сериализую Site приложение зацикливается из-за циклических ссылок. Поставить @JsonIgnore в сущности Organization у поля site нельзя, ибо в другом месте программы потребуется сериализовать сущность Organization как корневую, с сериализацией Organization как вложенной сущности. На помощь приходит MixIn. Делаю так:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.helan.adkiosk.entitiy.Advertiser;
import com.helan.adkiosk.entitiy.Site;

public interface OrganizationMixIn {

    @JsonIgnore
    public Site getSite();

    @JsonIgnore
    public Advertiser getAdvertiser();

}
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.helan.adkiosk.entitiy.Location;
import com.helan.adkiosk.entitiy.Member;

import java.util.Set;

public interface SiteWithOrganizationMixIn {

    @JsonIgnore
    public Set<Member> getMembers();

    @JsonIgnore
    public Set<Location> getLocations();

}
public String index() throws JsonProcessingException {
    ObjectMapper mapperWithMixIn = new ObjectMapper();
    mapperWithMixIn.addMixIn(Site.class, SiteWithOrganizationMixIn.class);
    mapperWithMixIn.addMixIn(Organization.class, OrganizationMixIn.class);
    return mapperWithMixIn.writeValueAsString(siteRepository.findAll());
}

Все работает как и задумывалось. Не устраивает только то, что я должен явно указывать поля в каждом MixIn, которые я не хочу сериализовывать с помощью аннотации JsonIgnore. Есть ли возможность реализовать обратную логику: по умолчанию сериализация отключена для всех полей, и в каждом MixIn я должен включить определенные поля? Или еще лучше, Изначально в сущности я указываю поля, которые сериализуются, а затем добавляю еще требуемые в каждом MixIn?

Еще вопрос, в mvc могу ли я не создавать в явном виде ObjectMapper и вызывать сериализацию в строку, а указать с помощью какой-нибудь аннотации используемые в сериализации набор MixIn и возвращать ссылку объект из метода контроллера?

 , ,

popov-aa ()

Непривилегированные контейнеры LXC в Centos7

Форум — Admin

Возможно ли? Вот, что у меня получается:

[popov@PopovServer ~]$ cat /etc/subuid
popov:100000:65536

[popov@PopovServer ~]$ cat /etc/subgid
popov:100000:65536

[popov@PopovServer ~]$ cat ~/.config/lxc/default.conf
lxc.network.type = veth
lxc.network.link = virbr0
lxc.network.flags = up
lxc.kmsg = 0
lxc.start.auto = 1
lxc.id_map = u 0 100000 65536
lxc.id_map = g 0 100000 65536

[popov@PopovServer ~]$ lxc-create -n test -t download -- -d centos -r 7 -a amd64
lxc: conf.c: lxc_map_ids: 3638 Missing newuidmap/newgidmap
error mapping child
setgid: Invalid argument
lxc_container: lxccontainer.c: do_create_container_dir: 767 Failed to chown container dir
lxc_container: lxc_create.c: main: 274 Error creating container test

[popov@PopovServer ~]$ cat /etc/sysctl.conf
net.ipv4.ip_forward = 1
kernel.unprivileged_userns_clone = 1

[popov@PopovServer ~]$ sudo sysctl -p /etc/sysctl.conf
[sudo] пароль для popov:
net.ipv4.ip_forward = 1
sysctl: cannot stat /proc/sys/kernel/unprivileged_userns_clone: Нет такого файла или каталога

[popov@PopovServer ~]$ uname -a
Linux PopovServer 4.18.5-1.el7.elrepo.x86_64 #1 SMP Fri Aug 24 11:35:05 EDT 2018 x86_64 x86_64 x86_64 GNU/Linux
В сети какая-то противоречивая информация. Якобы на стандартном (старом) ядре чего-то не хватает. Я обновил ядро из сторонних реп, но не помогло.

 , ,

popov-aa ()

LXC на CentOS7: Ошибка при операциях с маркером проверки подлинности

Форум — Admin

Добрый день. На только что установленном centos7 пытаюсь освоить lxc-контейнеры по одной из нескольких статей. Спотыкаюсь уже на второй команде.

[root@PopovServer lxc]# lxc-create -n CentOS-Rust -t centos
Host CPE ID from /etc/os-release: cpe:/o:centos:centos:7
Checking cache download in /var/cache/lxc/centos/x86_64/7/rootfs ...
Cache found. Updating...
Загружены модули: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirror.corbina.net
 * extras: mirror.reconn.ru
 * updates: mirror.reconn.ru
No packages marked for update
Загружены модули: fastestmirror
Сброс источников:base extras updates
0 package файлов удалены
Update finished
Copy /var/cache/lxc/centos/x86_64/7/rootfs to /var/lib/lxc/CentOS-Rust/rootfs ...
Copying rootfs to /var/lib/lxc/CentOS-Rust/rootfs ...
sed: невозможно прочитать /var/lib/lxc/CentOS-Rust/rootfs/etc/init/tty.conf: Нет такого файла или каталога
Storing root password in '/var/lib/lxc/CentOS-Rust/tmp_root_pass'
chpasswd: не удалось открыть /etc/passwd
Срок действия пароля пользователя root заканчивается.
passwd: Libuser error at line: 413 - Error replacing `/etc/passwd': Отказано в доступе.
passwd: Ошибка
sed: невозможно прочитать /var/lib/lxc/CentOS-Rust/rootfs/etc/rc.sysinit: Нет такого файла или каталога
sed: невозможно прочитать /var/lib/lxc/CentOS-Rust/rootfs/etc/rc.d/rc.sysinit: Нет такого файла или каталога

Container rootfs and config have been created.
Edit the config file to check/enable networking setup.

The temporary root password is stored in:

        '/var/lib/lxc/CentOS-Rust/tmp_root_pass'


The root password is set up as expired and will require it to be changed
at first login, which you should do as soon as possible.  If you lose the
root password or wish to change it without starting the container, you
can change it from the host by running the following command (which will
also reset the expired flag):

        chroot /var/lib/lxc/CentOS-Rust/rootfs passwd

[root@PopovServer lxc]# chroot /var/lib/lxc/CentOS-Rust/rootfs passwd
Изменяется пароль пользователя root.
Новый пароль :
Повторите ввод нового пароля :
passwd: Ошибка при операциях с маркером проверки подлинности
[root@PopovServer lxc]#

Пробовал и chroot делать на корень системы с вызовом passwd, и /etc/shadow удалял с последующим его генерированием трехбуквенной командой, уже забыл какой. Результат тот же.

Немного смущает, что у меня вывод слегка отличается от того, что в статье. Возможно при создании контейнера уже что-то пошло не так.

Например, вот: https://letsclearitup.com.ua/lxc/ustanovka-i-nastroyka-lxc-v-centos-7.html В статье:

Storing root password in '/var/lib/lxc/Lxc0/tmp_root_pass'
Expiring password for user root.
passwd: Success
У меня же:
Storing root password in '/var/lib/lxc/CentOS-Rust/tmp_root_pass'
chpasswd: не удалось открыть /etc/passwd
Срок действия пароля пользователя root заканчивается.
passwd: Libuser error at line: 413 - Error replacing `/etc/passwd': Отказано в доступе.
passwd: Ошибка

В чем может быть проблема?

[root@PopovServer lxc]# lxc-checkconfig
Kernel configuration not found at /proc/config.gz; searching...
Kernel configuration found at /boot/config-3.10.0-862.9.1.el7.x86_64
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
newuidmap is not installed
newgidmap is not installed
Network namespace: enabled
Multiple /dev/pts instances: enabled

--- Control groups ---
Cgroup: enabled
Cgroup clone_children flag: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled

--- Misc ---
Veth pair device: enabled
Macvlan: enabled
Vlan: enabled
Bridges: enabled
Advanced netfilter: enabled
CONFIG_NF_NAT_IPV4: enabled
CONFIG_NF_NAT_IPV6: enabled
CONFIG_IP_NF_TARGET_MASQUERADE: enabled
CONFIG_IP6_NF_TARGET_MASQUERADE: enabled
CONFIG_NETFILTER_XT_TARGET_CHECKSUM: enabled

--- Checkpoint/Restore ---
checkpoint restore: enabled
CONFIG_FHANDLE: enabled
CONFIG_EVENTFD: enabled
CONFIG_EPOLL: enabled
CONFIG_UNIX_DIAG: enabled
CONFIG_INET_DIAG: enabled
CONFIG_PACKET_DIAG: enabled
CONFIG_NETLINK_DIAG: enabled
File capabilities: enabled

Note : Before booting a new kernel, you can check its configuration
usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig

[root@PopovServer lxc]#

 ,

popov-aa ()

Программа для блокировки экрана по расписанию

Форум — Desktop

Коллега работает в gnome, я в xfce4. Я установил себе плагин, который принудительно с заданным интервалом устраивает перерыв, блокируя на это время экран. Все был бы доволен, но частенько бывает так, что коллега хочет чтобы я ему показал код, или наоборот, а у нас рассинхронизация. Либо он отдыхает, либо я. Подскажите программу с аналогичным функционалом, только чтобы перерыв происходил по расписанию, чтобы несколько человек были в одной фазе.

То есть чтобы каждую 55-ю минуту часа экран блокировался на пять минут, с возможностью отложить на минуту.

 ,

popov-aa ()

Регистрация в Selector из другого потока

Форум — Development

Я хочу написать класс, который работал бы с несколькими сокетами в одном потоке. Для этой цели как нельзя лучше подходят SocketChannel и Selector.

С серверной часть проблем нет:

        Selector selector = SelectorProvider.provider().openSelector();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.socket().bind(socketAddress);
        serverSocketChannel.register(selector, serverSocketChannel.validOps());

        try {
            while (selector.select() > -1) {
                Iterator<SelectionKey> selectionKeyIterator = selector.selectedKeys().iterator();
                while (selectionKeyIterator.hasNext()) {
                    SelectionKey selectionKey = selectionKeyIterator.next();
                    selectionKeyIterator.remove();

                    if (selectionKey.isValid()) {
                        if (!handleSelectionKey(selectionKey)) {
                            logger.debug("Unhandled selection key: " + selectionKey.hashCode() + ", " + selectionKey.readyOps());
                        }
                    }
                }
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }

Все по секретным документам с хабра =) Пришел новый клиент - обработали isAcceptable.

Проблема с клиентской частью. Допустим я хочу иметь возможность подключаться к нескольким сокетам и обрабатывать их в одном потоке.

Запускаю в одном потоке:

while (selector.select() > -1)
Теперь если из другого потока я вызову:
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        socketChannel.connect(socketAddress);
        socketChannel.register(selector, socketChannel.validOps());
И на register мы зависнем, ибо select захватил монитор и не отпускает его. Полагаю, что регистрироваться мы должны в том же потоке, где и происходит обработка select. Наверное нужно перед запуском цикла опроса Select зарегистрировать в нем на прослушивание своей операции аля WantToConnect, при возникновении необходимости подключиться к новому сокету из другого потока каким-то образом будить Selector, сообщать ему что пришло данное событие. Каким образом это можно сделать?

 , ,

popov-aa ()

Создание дочернего ApplicationContext в другом потоке

Форум — Development

Для изучения Java и сопутствующих технологий я поставил себе задачу: в свободное от работы время переписать рабочий проект с C++/Qt/OSGEarth на Java/NasaWorldWind.

Это позволит мне познакомиться и с Spring, и с Hibernate и Swing/JavaFX и с WorldWind.

Вот мой репозиторий проекта: https://github.com/popov-aa/GeoEditor Прошу не ругать стиль и отсутствие комментариев. Это чисто учебный проект.

Так как версии интерфейсов будет две, Swing и JavaFX, каждый со своим набором бинов, реализующих окна, я решил что в точке входа (класс com.popov.GeoEditor.GeoEditor) будет создаваться основной ApplicationContext, включающий в себя общие бины.

Далее ссылка на этот ApplicationContext в зависимости от аргументов запуска будет передаваться в объект отвечающий за запуск Swing (com.popov.GeoEditor.launcher.SwingLauncher) или JavaFX (com.popov.GeoEditor.launcher.JavaFXLauncher) версий, в которых будет создаваться свой дочерний ApplicationContext.

Когда я запускаю swing-версию никаких проблем нет:

mvn exec:java -Dexec.args="swing"
Создание всех ApplicationContext и бинов происходит в главном потоке приложения, а в конце просто отображается окно.

Когда запускается JavaFX-версия приложения, указатель на родительский ApplicationContext сохраняется как поле класса JavaFXLauncher и после этого запускается javafx.application.Application.

mvn exec:java -Dexec.args="javafx"

Если создавать дочерний ApplicationContext в потоке JavaFX, в методе start, указатель на родительский ApplicationContext уже будет равен null. Бины JavaFX не будут иметь доступа к общим бинам и ничего не запустится. Если создавать дочерний ApplicationContext в основном потоке, в методе, в который передается указатель на общий ApplicationContext, тогда приложение падает из-за попытке создания JavaFX-окон не в JavaFX-потоке, ибо бины не ленивые.

Собственно, вопрос: почему когда запускается JavaFX-поток обнуляется указатель на родительский ApplicationContext (JavaFXLauncher.generalApplicationContext)? Кто его обнуляет?

Я был уверен в том, что объект в Java будет существовать до тех пор, пока на него есть хоть одна ссылка. Ссылку generalApplicationContext я устанавливаю в методе launch(ApplicationContext applicationContext, String[] args) и больше нигде не модифицирую. И вдруг в другом потоке она оказывается равно null.

Есть какие-то правила, касательно того, что связанные друг с другом ApplicationContext должны быть созданы в одном и том же потоке? Я подобной информации не нашел.

И мне казалось, что в Java, в отличие от Qt, нет таких заморочек, ибо отсутствуют встроенные очереди событий.

 ,

popov-aa ()

Изучение Java

Форум — Development

Возникло жгучее желание изучить Java. Имеются два тома Кей С. Хортсманна и Гарри Корнелла Java2. Однако изучать старую версию фреймворка, и затем новинки каждой новой версии не очень рационально. Думаю лучше купить книгу для новичков по последней версии языка. Можете посоветовать конкретную книгу? Годный ли вот этот вариант: http://www.ozon.ru/context/detail/id/31249554/

 

popov-aa ()

RSS подписка на новые темы