{"id":398587,"date":"2024-06-29T14:09:52","date_gmt":"2024-06-29T14:09:52","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=398587"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=398587","title":{"rendered":"<span>Helidon, Testcontainers, Cucumber, Kafka \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c10\/95a\/36f\/c1095a36f65f6fab125563785149b402.png\" width=\"1264\" height=\"598\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c10\/95a\/36f\/c1095a36f65f6fab125563785149b402.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>Helidon<\/strong>\u00a0 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f\u00a0<strong>\u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432<\/strong>, \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0438 \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0432 \u043f\u0440\u043e\u0434\u0435, \u0438 \u0434\u0435\u043c\u043e\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u044f\u044e\u0449\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c!<\/p>\n<p>\u0410 \u043a\u0430\u043a \u043d\u0430\u0441\u0447\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Helidon?<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432, \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<h2>\u041f\u0440\u0435\u0434\u043c\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/h2>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0433\u043e\u0434\u043d\u044f.\u00a0\u042d\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Socks Shop, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e\u00a0<a href=\"https:\/\/github.com\/helidon-sockshop\/sockshop\" rel=\"noopener noreferrer nofollow\"><u>\u0437\u0434\u0435\u0441\u044c<\/u><\/a>\u00a0. \u0423 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c PetClinic, \u0430 \u0443 \u043d\u0430\u0441 \u0432\u043e\u0442 Socks Shop!<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432\u0441\u0435\u0433\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0448\u0442\u0443\u043a, \u043d\u043e \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435, \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e REST API \u0431\u0435\u0437 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430.\u00a0\u0423\u043f\u0440\u043e\u0441\u0442\u0438\u043c \u0432\u0441\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e!<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 Helidon MP \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u043d SockShopResource \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u043f\u043e\u043a\u0443\u043f\u043a\u0438 \u043d\u043e\u0441\u043a\u043e\u0432.\u00a0\u0415\u0441\u0442\u044c  \u043c\u0435\u0442\u043e\u0434 \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u043d\u043e\u0441\u043a\u0438 \u0441 \u0438\u0445 \u0446\u0435\u043d\u0430\u043c\u0438.\u00a0\u0418 \u0435\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434 POST, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u043e\u0440\u0437\u0438\u043d\u0443 \u0441 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c\u0438 \u0442\u043e\u0432\u0430\u0440\u0430\u043c\u0438.\u00a0\u041f\u043e\u0441\u043b\u0435 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430, \u0432 \u0441\u043b\u0443\u0436\u0431\u0443 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u043e\u0442\u043e\u0441\u043b\u0430\u0442\u044c \u0442\u043e\u0432\u0430\u0440.\u00a0\u0415\u0441\u0442\u044c \u0438 \u0438\u043d\u0432\u043e\u0438\u0441\u0438\u043d\u0433 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0438 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0447\u0435\u0442\u043e\u0432, \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 REST.\u00a0\u0412\u0441\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0441\u0430\u043c\u0438 \u0437\u0430\u0431\u043e\u0442\u044f\u0442\u0441\u044f \u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u0441\u0432\u043e\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 (\u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u0439 Hibernate:)).<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/047\/040\/9b3\/0470409b3f8ef70da91b49e4c6d5b7a9.png\" alt=\"\" title=\"\" width=\"841\" height=\"841\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/047\/040\/9b3\/0470409b3f8ef70da91b49e4c6d5b7a9.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0447\u0442\u043e\u0431\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043b\u0443\u0447\u0448\u0443\u044e \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e \u0434\u043b\u044f \u0435\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<h3>SockShopResource<\/h3>\n<p>\u0420\u0435\u0441\u0443\u0440\u0441 Socks Shop &#8212; \u044d\u0442\u043e \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0439 REST endpoint, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430:<\/p>\n<pre><code class=\"java\">private ShoppingService shoppingService;  @Inject public SockShopResource(ShoppingService shoppingService) {     this.shoppingService = shoppingService; }   @POST public Response checkout(ShoppingCart shoppingCart){     long id = shoppingService.checkout(shoppingCart);      UriBuilder responseUri = UriBuilder.fromResource(SockShopResource.class);     responseUri.path(Long.toString(id));     return Response.created(responseUri.build()).build(); }<\/code><\/pre>\n<h3>ShoppingService<\/h3>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430.\u00a0\u0421\u0435\u0440\u0432\u0438\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043a\u043e\u0440\u0437\u0438\u043d\u0443 \u043f\u043e\u043a\u0443\u043f\u043e\u043a:<\/p>\n<pre><code class=\"java\">@ApplicationScoped public class ShoppingService {      private final SubmissionPublisher&lt;String> emitter = new SubmissionPublisher&lt;>();      @PersistenceContext(unitName = \"test\")     private EntityManager entityManager;      @Inject     @RestClient     private InvoicingClient invoicingClient;       @Transactional     public long checkout(ShoppingCart shoppingCart){         entityManager.persist(shoppingCart);         Long id = shoppingCart.getId();         emitter.submit(String.valueOf(id));         invoicingClient.handleInvoice(shoppingCart);         return id;     }      @Outgoing(\"outgoing-delivery\")     public Publisher&lt;String> preparePublisher() {         \/\/ Create new publisher for emitting to by this::process         return ReactiveStreams                 .fromPublisher(FlowAdapters.toPublisher(emitter))                 .buildRs();     } }<\/code><\/pre>\n<p>&#8230; \u0438 \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u043a\u0430\u0443\u0442, \u0432 \u0441\u043b\u0443\u0436\u0431\u0443 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0441\u043a\u0438 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438\u0445 \u041a\u043b\u0438\u0435\u043d\u0442\u0443.\u00a0\u0422\u0430\u043a\u0436\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0432\u043e\u0439\u0441\u0438\u043d\u0433 \u0441\u0435\u0440\u0432\u0438\u0441 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e MicroProfile \u00abRestClient\u00bb, \u0434\u043b\u044f \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0447\u0435\u0442\u0430.<\/p>\n<h3>\u0421\u043b\u0443\u0436\u0431\u0430 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438<\/h3>\n<p>\u0412\u0441\u044f\u043a\u0438\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u043d\u043e\u0432\u043e\u0439 \u043f\u043e\u043a\u0443\u043f\u043a\u0435, \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.\u00a0\u0410\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f <code>@Incomming<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442.<\/p>\n<pre><code class=\"java\">@ApplicationScoped public class DeliveryService {      @PersistenceContext(unitName = \"test\")     private EntityManager entityManager;       @Incoming(\"incoming-delivery\")     @Transactional     public void deliverToCustomer(String cartId){         Delivery delivery = new Delivery();         delivery.setShoppingCartId(Long.parseLong(cartId));         entityManager.persist(delivery);     } }<\/code><\/pre>\n<p>\u0415\u0441\u0442\u044c \u0442\u0430\u043a \u0436\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \ud83d\ude42<\/p>\n<h3>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/h3>\n<p>\u2026 \u043e\u043d\u0430 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f.\u00a0\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0411\u0414 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 messaging-a.\u00a0\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c H2 DB \u0438 ActiveMQ:<\/p>\n<pre><code class=\"bash\">#Database javax.sql.DataSource.test.dataSourceClassName=org.h2.jdbcx.JdbcDataSource javax.sql.DataSource.test.dataSource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false javax.sql.DataSource.test.dataSource.user=sa javax.sql.DataSource.test.dataSource.password=  #Messaging mp.messaging.connector.helidon-jms.jndi.env-properties.java.naming.provider.url=vm:\/\/localhost?broker.persistent=false mp.messaging.connector.helidon-jms.jndi.env-properties.java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory mp.messaging.incoming.incoming-delivery.connector=helidon-jms mp.messaging.incoming.incoming-delivery.type=queue mp.messaging.incoming.incoming-delivery.destination=delivery  mp.messaging.outgoing.outgoing-delivery.connector=helidon-jms mp.messaging.outgoing.outgoing-delivery.type=queue mp.messaging.outgoing.outgoing-delivery.destination=delivery<\/code><\/pre>\n<p>\u041d\u0430\u043c \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e!<\/p>\n<p>\u042d\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432\u00a0<code>microprofile-config.properties<\/code>\u0444\u0430\u0439\u043b.\u00a0\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043e\u0447\u0435\u043d\u044c portable.<\/p>\n<h3>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u0444\u0430\u0439\u043b\u044b<\/h3>\n<p><code>AppInitialiser<\/code>\u00a0\u041a\u043b\u0430\u0441\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 messaging-a:<\/p>\n<pre><code class=\"java\">@ApplicationScoped public class AppInitializer {      @PersistenceContext(unitName = \"test\")     private EntityManager entityManager;      @Transactional     void onStartup(@Observes @Initialized(ApplicationScoped.class) final Object event) {         Socks model1 = new Socks(1L, \"Model1\", 10.00);         entityManager.persist(model1);         Socks model2 = new Socks(2L, \"Model2\", 20.00);         entityManager.persist(model2);          Client client1 = new Client(1L, \"Joe\", \"Doe\", \"Somewhere\", \"12345\");         entityManager.persist(client1);          ShoppingCart cart = new ShoppingCart();         cart.setId(1L);         cart.setClient(client1);         cart.setCart(List.of(model1, model2));         entityManager.persist(cart);          entityManager.flush();     }      private void makeConnections(@Observes @Priority(PLATFORM_AFTER + 1) @Initialized(ApplicationScoped.class) Object event) throws Throwable{          ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(\"vm:\/\/localhost?broker.persistent=false\");         Connection connection = connectionFactory.createConnection();         connection.createSession(false, 1);      } }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c \u043c\u043e\u043c\u0435\u043d\u0442a, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435\u00a0<code>ApplicationScoped<\/code>bean-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u044b \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442. \u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e event \u043e\u0431 \u044d\u0442\u043e\u043c \u0432\u044b\u0441\u0442\u0440\u0435\u043b\u0438\u043b, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c  \u0434\u0430\u043d\u043d\u044b\u0435.\u00a0\u042d\u0442\u043e \u0447\u0438\u0441\u0442\u044b\u0439 CDI.\u00a0\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043d\u0430 100% portable.<\/p>\n<h3>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0435 \u044d\u0442\u043e \u043d\u0430\u0434\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c!<\/h3>\n<h3>Unit testing<\/h3>\n<p>\u042d\u0442\u043e, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0441\u0430\u043c\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043d\u043e \u0431\u0435\u0437 \u043d\u0435\u0433\u043e \u043d\u0438\u043a\u0430\u043a!<\/p>\n<p>\u0412\u0441\u0435, \u0447\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0411\u0414 \u0438\u043b\u0438 \u043b\u044e\u0431\u044b\u043c\u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438 \u0441\u043b\u0443\u0436\u0431\u0430\u043c\u0438, \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0438\u043c\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u043c\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 CDI, \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u043e\u043a\u0430\u043c\u0438.\u00a0\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f\u00a0<code>mockito<\/code>\u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e:<\/p>\n<pre><code>@ExtendWith(MockitoExtension.class) public class SockShopResourceMockTest {      private List&lt;Socks> socksList = List.of(new Socks(1L, \"Model1\", 10.00),             new Socks(2L, \"Model2\", 20.00));      @InjectMocks     private SockShopResource sockShopResource;      @Mock     private ShoppingService shoppingService;      @BeforeEach     private void init() {         Mockito.lenient().doCallRealMethod().when(shoppingService).allSocks();     }      @Test     void allSocksTest() {         Mockito.doReturn(socksList).when(shoppingService).allSocks();          String response = sockShopResource.allSocks();         assertEquals(response, \"[{\\\"id\\\":1,\\\"model\\\":\\\"Model1\\\",\\\"price\\\":10.0},{\\\"id\\\":2,\\\"model\\\":\\\"Model2\\\",\\\"price\\\":20.0}]\");         Mockito.verifyNoMoreInteractions(shoppingService);      } }<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435,\u00a0<code>ShoppingService<\/code>\u044d\u0442\u043e \u043c\u043e\u043a, \u0438 \u043c\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c SockShopResource \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.\u00a0\u0422\u0430\u043a\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u043e, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d.<\/p>\n<h3>@HelidonTest<\/h3>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e, \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0433\u043b\u0443\u0431\u0438\u043c\u0441\u044f \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0433\u043e Helidon.<\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0439 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 &#8212; <code>@HelidonTest.<\/code>\u041e\u043d\u0430 \u0431\u0435\u0440\u0435\u0442 \u043d\u0430 \u0441\u0435\u0431\u044f \u0432\u0441\u0435 \u0437\u0430\u0431\u043e\u0442\u044b \u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u0432\u0441\u0435\u0433\u043e.<\/p>\n<pre><code class=\"java\">@HelidonTest public class TestSocksResource {      @Inject     WebTarget webTarget;      @Test     void testAllSocks(){          JsonArray jsonObject = webTarget.path(\"\/api\/shop\/allSocks\")                 .request()                 .get(JsonArray.class);          assertEquals(\"[{\\\"model\\\":\\\"Model1\\\",\\\"price\\\":10.0},{\\\"model\\\":\\\"Model2\\\",\\\"price\\\":20.0}]\",jsonObject.toString());     } } <\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u043d\u043e\u0439 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u043c\u044b \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c Helidon MP, \u0432\u0441\u0435 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 CDI \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0442\u0441\u044f.  \u0422\u0430\u043a \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.\u00a0\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u00a0<code>WebTarget<\/code>\u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0438\u0445 REST \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432.<\/p>\n<p>\u0421 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f\u043c\u0438, \u0442\u0430\u043a\u0438\u043c\u0438, \u043a\u0430\u043a \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"java\">@DisableDiscovery  @AddExtension (ConfigCdiExtension.class)  @AddBean (SocksTest.ConfiguredBean.class)  @AddConfig (key = \"test.message\", value = \"Socks!\")<\/code><\/pre>\n<p>&#8230; \u0442\u0435\u0441\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c!<\/p>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u044d\u0442\u0438\u0445 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u0431\u043b\u043e\u0433 \u043f\u043e\u0441\u0442\u0435\u00a0<a href=\"https:\/\/medium.com\/helidon\/testing-helidon-9df2ea14e22\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/medium.com\/helidon\/testing-helidon-9df2ea14e22<\/u><\/a><\/p>\n<h3>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Testcontainers<\/h3>\n<p><a href=\"https:\/\/www.testcontainers.org\/\" rel=\"noopener noreferrer nofollow\">Testcontainers<\/a> &#8212; \u044d\u0442\u043e \u043f\u043e-\u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u043c\u0443 \u0448\u0435\u0434\u0435\u0432\u0440\u0430\u043b\u044c\u043d\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u043d\u043e\u0432\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c.\u00a0\u0421 \u0438\u0445 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c Helidon, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430:<\/p>\n<pre><code class=\"java\">protected static final String NETWORK_ALIAS_APPLICATION = \"application\";  protected static final Network NETWORK = Network.newNetwork();  protected static final GenericContainer&lt;?> APPLICATION = new GenericContainer&lt;>(\"socks-shop:latest\")     .withExposedPorts(8080)     .withNetwork(NETWORK)     .withNetworkAliases(NETWORK_ALIAS_APPLICATION)     .withEnv(\"JAVA_OPTS\", \"-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true\")     .waitingFor(Wait.forHealthcheck());  static {   APPLICATION.start(); }<\/code><\/pre>\n<p>Generic Container \u0432\u043f\u043e\u043b\u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e.\u00a0\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u043e\u043a\u0435\u0440 \u043e\u0431\u0440\u0430\u0437\u0430 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u00a0<code>docker-maven-plugin<\/code>\u043e\u0442 Spotify:<\/p>\n<pre><code class=\"xml\">&lt;plugin>     &lt;groupId>com.spotify&lt;\/groupId>     &lt;artifactId>dockerfile-maven-plugin&lt;\/artifactId>     &lt;version>1.4.13&lt;\/version>     &lt;configuration>         &lt;repository>${project.build.finalName}&lt;\/repository>         &lt;buildArgs>             &lt;JAR_FILE>${project.build.finalName}.jar&lt;\/JAR_FILE>         &lt;\/buildArgs>         &lt;skipDockerInfo>true&lt;\/skipDockerInfo>     &lt;\/configuration>     &lt;executions>         &lt;execution>             &lt;phase>package&lt;\/phase>             &lt;goals>                 &lt;goal>build&lt;\/goal>             &lt;\/goals>         &lt;\/execution>     &lt;\/executions> &lt;\/plugin><\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0435, \u043a\u0430\u043a \u0434\u043e\u043a\u0435\u0440 \u043e\u0431\u0440\u0430\u0437 \u0438 \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u043e\u0435 \u043a\u0430\u043a Testcontainer, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u043f\u043e\u043b\u043d\u043e\u043c\u0430\u0441\u0448\u0442\u0430\u0431\u043d\u043e\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435.<\/p>\n<p>\u0425\u043e\u0440\u043e\u0448\u0438\u043c \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a\u043e\u043c \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a <a href=\"https:\/\/cucumber.io\/\" rel=\"noopener noreferrer nofollow\">Cucumber<\/a>.\u00a0<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u043f\u043e\u043a\u0443\u043f\u043a\u0438 \u043d\u043e\u0441\u043a\u043e\u0432:<\/p>\n<pre><code class=\"bash\">Feature: BuySocks    Scenario: Buy one pair of socks     Given a user makes a checkout     When the checkout is performed     Then submitted to delivery<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043a\u0430\u0436\u0435\u043c Cucumber, \u043e\u0442\u043a\u0443\u0434\u0430 \u0447\u0438\u0442\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439:<\/p>\n<pre><code class=\"java\">@RunWith(Cucumber.class) @CucumberOptions(plugin = {\"pretty\"}, features = \"src\/test\/resources\/it\/feature\") public class SocksShopCucumberIT {   ... }<\/code><\/pre>\n<p>\u0418 \u0442\u0430\u043a, \u043c\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0435 \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435.\u00a0\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0435\u0433\u043e:<\/p>\n<pre><code class=\"java\">@Before public void beforeScenario() {     APPLICATION.withLogConsumer(new Slf4jLogConsumer(LOG));     requestSpecification = new RequestSpecBuilder()             .setPort(APPLICATION.getFirstMappedPort())             .build(); }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0448\u0430\u0433 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f:<\/p>\n<pre><code class=\"java\">@Given(\"a user makes a checkout\") public void a_user_makes_a_checkout() {     Socks socks = new Socks(100l, \"Model1\", 10.0);     Client client1 = new Client(100L, \"Joe\", \"Doe\", \"Somewhere\", \"12345\");     ShoppingCart shoppingCart = new ShoppingCart();     shoppingCart.setId(100L);     shoppingCart.setClient(client1);     shoppingCart.setCart(List.of(socks));      RestAssured.given(requestSpecification)             .contentType(MediaType.APPLICATION_JSON)             .body(shoppingCart)             .when()             .post(\"\/api\/shop\/\")             .then()             .statusCode(Response.Status.CREATED.getStatusCode()); }<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u0430\u0437\u0430:<\/p>\n<pre><code class=\"java\">@When(\"the checkout is performed\") public void the_checkout_is_performed() {     RestAssured.given(requestSpecification)             .accept(MediaType.APPLICATION_JSON)             .when()             .get(\"\/api\/shop\/status\/100\")             .then()             .statusCode(Response.Status.OK.getStatusCode())             .contentType(MediaType.APPLICATION_JSON)             .body(Matchers                     .equalTo(\"{\\\"cart\\\":[{\\\"id\\\":100,\\\"model\\\":\\\"Model1\\\",\\\"price\\\":10.0}],\\\"client\\\":{\\\"address\\\":\\\"Somewhere\\\",\\\"firstName\\\":\\\"Joe\\\",\\\"id\\\":100,\\\"lastName\\\":\\\"Doe\\\",\\\"postcode\\\":\\\"12345\\\"},\\\"id\\\":100}\"));  } <\/code><\/pre>\n<p>\u2026 \u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0431\u044b\u043b\u043e \u043b\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0435, \u0438 \u043f\u043e\u043a\u0443\u043f\u043a\u0430 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0430 \u200b\u200b\u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438:<\/p>\n<pre><code class=\"java\">@Then(\"submitted to delivery\") public void submitted_to_delivery() throws InterruptedException {     Thread.sleep(500);\/\/wait the message to arrive     RestAssured.given(requestSpecification)             .when()             .get(\"\/api\/delivery\/status\/100\")             .then()             .statusCode(Response.Status.OK.getStatusCode())             .contentType(MediaType.APPLICATION_JSON)             .body(Matchers                     .equalTo(\"{\\\"id\\\":1,\\\"shoppingCartId\\\":100}\")); }<\/code><\/pre>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u044d\u0442\u043e\u0442 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439, \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ol>\n<li>\n<p>Testcontainers \u0431\u0435\u0440\u0435\u0442 \u0441\u0430\u043c\u044b\u0439 \u0441\u0432\u0435\u0436\u0438\u0439 \u043e\u0431\u0440\u0430\u0437\u00a0<code>socks-shop<\/code>\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0435\u0433\u043e;<\/p>\n<\/li>\n<li>\n<p><code>Socks-shop<\/code>\u00a0\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430;<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f `a_user_makes_a_checkout ()`;<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0448\u0442\u0430\u0442\u043d\u043e, the_checkout_is_performed() \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0437\u0430\u043a\u0430\u0437 \u043f\u0435\u0440\u0441\u0438\u0441\u0442\u0438\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p>\u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, the_checkout_is_performed() \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d \u043b\u0438 \u0437\u0430\u043a\u0430\u0437.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0435\u0441\u0442 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u043c, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u044d\u0442\u0430\u043f\u044b \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u044b.<\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c in memory H2 \u0438 in memory Messaging, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f.<\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Helidon \u0432 \u00ab\u043f\u043e\u0447\u0442\u0438 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u00bb \u0441\u0440\u0435\u0434\u0435.\u00a0<\/p>\n<h3>\u2026\u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442<\/h3>\n<p>\u0421 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438 \u0438 Helidon \u043c\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442. \u0414\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c Helidon \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u043e\u0442 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0441\u043b\u0443\u0436\u0431, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0445\u043e\u0440\u043e\u0440\u043e \u043b\u0438 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 MariaDB \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 Kafka \u0434\u043b\u044f \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438.\u00a0\u041e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432.\u00a0\u041d\u0430\u043c \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0443\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043d\u043e\u0432\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e @HelidonTest \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 Helidon.\u00a0\u041d\u043e \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043a\u043e\u043d\u0444\u0438\u0433 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u043e\u0431\u0449\u0438\u0442\u044c \u043e\u0431 \u044d\u0442\u043e\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"java\">@Configuration(useExisting = true)<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 MariaDB \u0438 Kafka \u0438 \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430:<\/p>\n<pre><code class=\"java\">private static MariaDBContainer&lt;?> db = new MariaDBContainer&lt;>(\"mariadb:10.3.6\")         .withDatabaseName(\"mydb\")         .withUsername(\"test\")         .withPassword(\"test\"); static KafkaContainer kafka = new KafkaContainer();  @BeforeAll public static void setup() {     kafka.start();      Map&lt;String, String> configValues = new HashMap&lt;>();     configValues.put(\"mp.initializer.allow\", \"true\");     configValues.put(\"mp.messaging.incoming.from-kafka.connector\", \"helidon-kafka\");     configValues.put(\"mp.messaging.incoming.from-kafka.topic\", \"delivery\");     configValues.put(\"mp.messaging.incoming.from-kafka.auto.offset.reset\", \"latest\");     configValues.put(\"mp.messaging.incoming.from-kafka.enable.auto.commit\", \"true\");     configValues.put(\"mp.messaging.incoming.from-kafka.group.id\", \"helidon-group-1\");      configValues.put(\"mp.messaging.outgoing.to-kafka.connector\", \"helidon-kafka\");     configValues.put(\"mp.messaging.outgoing.to-kafka.topic\", \"delivery\");      configValues.put(\"mp.messaging.outgoing.test-delivery.connector\", \"helidon-kafka\");     configValues.put(\"mp.messaging.outgoing.test-delivery.topic\", \"delivery\");      configValues.put(KafkaConnector.CONNECTOR_PREFIX + \"helidon-kafka.bootstrap.servers\", kafka.getBootstrapServers());     configValues.put(KafkaConnector.CONNECTOR_PREFIX + \"helidon-kafka.key.serializer\", \"org.apache.kafka.common.serialization.StringSerializer\");     configValues.put(KafkaConnector.CONNECTOR_PREFIX + \"helidon-kafka.value.serializer\", \"org.apache.kafka.common.serialization.StringSerializer\");     configValues.put(KafkaConnector.CONNECTOR_PREFIX + \"helidon-kafka.key.deserializer\", \"org.apache.kafka.common.serialization.StringDeserializer\");     configValues.put(KafkaConnector.CONNECTOR_PREFIX + \"helidon-kafka.value.deserializer\", \"org.apache.kafka.common.s\" +             \"erialization.StringDeserializer\");      configValues.put(\"mp.initializer.allow\", \"true\");     configValues.put(\"javax.sql.DataSource.test.dataSourceClassName\", \"org.mariadb.jdbc.MariaDbDataSource\");     configValues.put(\"javax.sql.DataSource.test.dataSource.url\", db.getJdbcUrl());     configValues.put(\"javax.sql.DataSource.test.dataSource.user\", db.getUsername());     configValues.put(\"javax.sql.DataSource.test.dataSource.password\", db.getPassword());     org.eclipse.microprofile.config.Config mpConfig = ConfigProviderResolver.instance()             .getBuilder()             .withSources(MpConfigSources.create(configValues))             .build();     ConfigProviderResolver.instance().registerConfig(mpConfig, Thread.currentThread().getContextClassLoader()); }<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0445\u043e\u0440\u043e\u0448\u043e, \u0447\u0442\u043e \u0414\u0435\u0432\u0443\u0448\u043a\u0438 \u0438 \u0420\u0435\u0431\u044f\u0442\u0430 \u0438\u0437 Test Container \u0443\u0436\u0435 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043b\u0438 \u0434\u043b\u044f \u043d\u0430\u0441 MariaDB \u0438 Kafka \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b!<\/p>\n<p>\u0412\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e!\u00a0\u0415\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u044d\u0442\u043e\u0442 \u0442\u0435\u0441\u0442 (\u0434\u0430\u0436\u0435 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438\u0437 IDE), \u043e\u043d \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b, \u0430 \u043f\u043e\u0441\u043b\u0435 \u0438\u0445 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b, \u0438 Helidon \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f.\u00a0\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u044d\u0442\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432.\u00a0\u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043a MariaDB, \u0430 \u0432\u0441\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f &#8212; \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0447\u0435\u0440\u0435\u0437 Kafka.\u00a0\u0418\u0434\u0435\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0435\u043b\u0438\u043a\u043e\u043b\u0435\u043f\u043d\u0430!<\/p>\n<h3>\u041c\u0435\u0442\u0430-\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0441\u0442\u043e\u0438\u0442 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0444\u0438\u0448\u043a\u0443 Helidon MP &#8212; \u043c\u0435\u0442\u0430-\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0430\u043c Config \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u0435\u0442\u0430-\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Helidon MP Config.<\/p>\n<p>\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f MicroProfile \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0438 \u0444\u043b\u0430\u0433\u0438, \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0432 \u043c\u0435\u0442\u0430-\u0444\u0430\u0439\u043b\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438.<\/p>\n<p>\u041c\u0435\u0442\u0430-\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0438 \u0440\u0430\u0437\u043d\u044b\u0445 \u043a\u043e\u043d\u0432\u0435\u0442\u0435\u0440\u043e\u0432.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0441 \u0438\u043c\u0435\u043d\u0435\u043c\u00a0<code>mp-meta-config.yaml<\/code>\u0438\u043b\u0438\u00a0<code>mp-meta-config.properties<\/code>\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u0438\u043b\u0438 \u0432 \u043a\u043b\u0430\u0441\u0441\u043f\u0430\u0441\u0435, \u0438 \u0432 \u043a\u043e\u0434\u0435 \u043d\u0435\u0442 \u044f\u0432\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0438\u0437\u00a0<code>meta-config<\/code>\u0444\u0430\u0439\u043b\u0430.\u00a0\u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u00a0<code>io.helidon.config.mp.meta-config<\/code>\u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u044b.<code>HELIDON_MP_META_CONFIG.<\/code><\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>Helidon \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u043b\u043d\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u043c\u044b\u0448\u043b\u0435\u043d\u043d\u044b\u0445 \u0438 \u0434\u0435 \u0444\u0430\u043a\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0439 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.\u00a0\u041c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u0435 \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 &#8212; \u043d\u0435\u043e\u0442\u044a\u0435\u043c\u043b\u0435\u043c\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f.\u00a0\u0425\u043e\u0440\u043e\u0448\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u044e\u0442 \u043b\u0443\u0447\u0448\u0435\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0430\u0448\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c! \u0422\u0430\u043a \u0447\u0442\u043e, \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0438\u0448\u0438\u0442\u0435 \u0442\u0435\u0441\u0442\u044b!<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u0438\u0433\u0440\u0430\u0442\u044c \u0441 \u043a\u043e\u0434\u043e\u043c \u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 &#8212;  \u043e\u043d \u043b\u0435\u0436\u0438\u0442\u00a0<a href=\"https:\/\/github.com\/dalexandrov\/socks-shop\" rel=\"noopener noreferrer nofollow\"><u>\u0437\u0434\u0435\u0441\u044c<\/u><\/a>\u00a0.<\/p>\n<p>\u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \ud83d\ude42<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/591655\/\"> https:\/\/habr.com\/ru\/articles\/591655\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>Helidon<\/strong>\u00a0 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f\u00a0<strong>\u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432<\/strong>, \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0438 \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0432 \u043f\u0440\u043e\u0434\u0435, \u0438 \u0434\u0435\u043c\u043e\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u044f\u044e\u0449\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c!<\/p>\n<p>\u0410 \u043a\u0430\u043a \u043d\u0430\u0441\u0447\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Helidon?<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432, \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<h2>\u041f\u0440\u0435\u0434\u043c\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/h2>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0433\u043e\u0434\u043d\u044f.\u00a0\u042d\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Socks Shop, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e\u00a0<a href=\"https:\/\/github.com\/helidon-sockshop\/sockshop\" rel=\"noopener noreferrer nofollow\"><u>\u0437\u0434\u0435\u0441\u044c<\/u><\/a>\u00a0. \u0423 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c PetClinic, \u0430 \u0443 \u043d\u0430\u0441 \u0432\u043e\u0442 Socks Shop!<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432\u0441\u0435\u0433\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0448\u0442\u0443\u043a, \u043d\u043e \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435, \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e REST API \u0431\u0435\u0437 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430.\u00a0\u0423\u043f\u0440\u043e\u0441\u0442\u0438\u043c \u0432\u0441\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e!<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 Helidon MP \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u043d SockShopResource \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u043f\u043e\u043a\u0443\u043f\u043a\u0438 \u043d\u043e\u0441\u043a\u043e\u0432.\u00a0\u0415\u0441\u0442\u044c  \u043c\u0435\u0442\u043e\u0434 \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u043d\u043e\u0441\u043a\u0438 \u0441 \u0438\u0445 \u0446\u0435\u043d\u0430\u043c\u0438.\u00a0\u0418 \u0435\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434 POST, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u043e\u0440\u0437\u0438\u043d\u0443 \u0441 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c\u0438 \u0442\u043e\u0432\u0430\u0440\u0430\u043c\u0438.\u00a0\u041f\u043e\u0441\u043b\u0435 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430, \u0432 \u0441\u043b\u0443\u0436\u0431\u0443 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u043e\u0442\u043e\u0441\u043b\u0430\u0442\u044c \u0442\u043e\u0432\u0430\u0440.\u00a0\u0415\u0441\u0442\u044c \u0438 \u0438\u043d\u0432\u043e\u0438\u0441\u0438\u043d\u0433 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0438 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0447\u0435\u0442\u043e\u0432, \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 REST.\u00a0\u0412\u0441\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0441\u0430\u043c\u0438 \u0437\u0430\u0431\u043e\u0442\u044f\u0442\u0441\u044f \u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u0441\u0432\u043e\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 (\u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u0439 Hibernate:)).<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0447\u0442\u043e\u0431\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043b\u0443\u0447\u0448\u0443\u044e \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e \u0434\u043b\u044f \u0435\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<h3>SockShopResource<\/h3>\n<p>\u0420\u0435\u0441\u0443\u0440\u0441 Socks Shop &#8212; \u044d\u0442\u043e \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0439 REST endpoint, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430:<\/p>\n<pre><code class=\"java\">private ShoppingService shoppingService;  @Inject public SockShopResource(ShoppingService shoppingService) {     this.shoppingService = shoppingService; }   @POST public Response checkout(ShoppingCart shoppingCart){     long id = shoppingService.checkout(shoppingCart);      UriBuilder responseUri = UriBuilder.fromResource(SockShopResource.class);     responseUri.path(Long.toString(id));     return Response.created(responseUri.build()).build(); }<\/code><\/pre>\n<h3>ShoppingService<\/h3>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430.\u00a0\u0421\u0435\u0440\u0432\u0438\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043a\u043e\u0440\u0437\u0438\u043d\u0443 \u043f\u043e\u043a\u0443\u043f\u043e\u043a:<\/p>\n<pre><code class=\"java\">@ApplicationScoped public class ShoppingService {      private final SubmissionPublisher&lt;String> emitter = new SubmissionPublisher&lt;>();      @PersistenceContext(unitName = \"test\")     private EntityManager entityManager;      @Inject     @RestClient     private InvoicingClient invoicingClient;       @Transactional     public long checkout(ShoppingCart shoppingCart){         entityManager.persist(shoppingCart);         Long id = shoppingCart.getId();         emitter.submit(String.valueOf(id));         invoicingClient.handleInvoice(shoppingCart);         return id;     }      @Outgoing(\"outgoing-delivery\")     public Publisher&lt;String> preparePublisher() {         \/\/ Create new publisher for emitting to by this::process         return ReactiveStreams                 .fromPublisher(FlowAdapters.toPublisher(emitter))                 .buildRs();     } }<\/code><\/pre>\n<p>&#8230; \u0438 \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u043a\u0430\u0443\u0442, \u0432 \u0441\u043b\u0443\u0436\u0431\u0443 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0441\u043a\u0438 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438\u0445 \u041a\u043b\u0438\u0435\u043d\u0442\u0443.\u00a0\u0422\u0430\u043a\u0436\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0432\u043e\u0439\u0441\u0438\u043d\u0433 \u0441\u0435\u0440\u0432\u0438\u0441 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e MicroProfile \u00abRestClient\u00bb, \u0434\u043b\u044f \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0447\u0435\u0442\u0430.<\/p>\n<h3>\u0421\u043b\u0443\u0436\u0431\u0430 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438<\/h3>\n<p>\u0412\u0441\u044f\u043a\u0438\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u043d\u043e\u0432\u043e\u0439 \u043f\u043e\u043a\u0443\u043f\u043a\u0435, \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.\u00a0\u0410\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f <code>@Incomming<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442.<\/p>\n<pre><code class=\"java\">@ApplicationScoped public class DeliveryService {      @PersistenceContext(unitName = \"test\")     private EntityManager entityManager;       @Incoming(\"incoming-delivery\")     @Transactional     public void deliverToCustomer(String cartId){         Delivery delivery = new Delivery();         delivery.setShoppingCartId(Long.parseLong(cartId));         entityManager.persist(delivery);     } }<\/code><\/pre>\n<p>\u0415\u0441\u0442\u044c \u0442\u0430\u043a \u0436\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \ud83d\ude42<\/p>\n<h3>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/h3>\n<p>\u2026 \u043e\u043d\u0430 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f.\u00a0\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0411\u0414 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 messaging-a.\u00a0\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c H2 DB \u0438 ActiveMQ:<\/p>\n<pre><code class=\"bash\">#Database javax.sql.DataSource.test.dataSourceClassName=org.h2.jdbcx.JdbcDataSource javax.sql.DataSource.test.dataSource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false javax.sql.DataSource.test.dataSource.user=sa javax.sql.DataSource.test.dataSource.password=  #Messaging mp.messaging.connector.helidon-jms.jndi.env-properties.java.naming.provider.url=vm:\/\/localhost?broker.persistent=false mp.messaging.connector.helidon-jms.jndi.env-properties.java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory mp.messaging.incoming.incoming-delivery.connector=helidon-jms mp.messaging.incoming.incoming-delivery.type=queue mp.messaging.incoming.incoming-delivery.destination=delivery  mp.messaging.outgoing.outgoing-delivery.connector=helidon-jms mp.messaging.outgoing.outgoing-delivery.type=queue mp.messaging.outgoing.outgoing-delivery.destination=delivery<\/code><\/pre>\n<p>\u041d\u0430\u043c \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e!<\/p>\n<p>\u042d\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432\u00a0<code>microprofile-config.properties<\/code>\u0444\u0430\u0439\u043b.\u00a0\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043e\u0447\u0435\u043d\u044c portable.<\/p>\n<h3>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u0444\u0430\u0439\u043b\u044b<\/h3>\n<p><code>AppInitialiser<\/code>\u00a0\u041a\u043b\u0430\u0441\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 messaging-a:<\/p>\n<pre><code class=\"java\">@ApplicationScoped public class AppInitializer {      @PersistenceContext(unitName = \"test\")     private EntityManager entityManager;      @Transactional     void onStartup(@Observes @Initialized(ApplicationScoped.class) final Object event) {         Socks model1 = new Socks(1L, \"Model1\", 10.00);         entityManager.persist(model1);         Socks model2 = new Socks(2L, \"Model2\", 20.00);         entityManager.persist(model2);          Client client1 = new Client(1L, \"Joe\", \"Doe\", \"Somewhere\", \"12345\");         entityManager.persist(client1);          ShoppingCart cart = new ShoppingCart();         cart.setId(1L);         cart.setClient(client1);         cart.setCart(List.of(model1, model2));         entityManager.persist(cart);          entityManager.flush();     }      private void makeConnections(@Observes @Priority(PLATFORM_AFTER + 1) @Initialized(ApplicationScoped.class) Object event) throws Throwable{          ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(\"vm:\/\/localhost?broker.persistent=false\");         Connection connection = connectionFactory.createConnection();         connection.createSession(false, 1);      } }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c \u043c\u043e\u043c\u0435\u043d\u0442a, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435\u00a0<code>ApplicationScoped<\/code>bean-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u044b \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442. \u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e event \u043e\u0431 \u044d\u0442\u043e\u043c \u0432\u044b\u0441\u0442\u0440\u0435\u043b\u0438\u043b, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c  \u0434\u0430\u043d\u043d\u044b\u0435.\u00a0\u042d\u0442\u043e \u0447\u0438\u0441\u0442\u044b\u0439 CDI.\u00a0\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043d\u0430 100% portable.<\/p>\n<h3>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0435 \u044d\u0442\u043e \u043d\u0430\u0434\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c!<\/h3>\n<h3>Unit testing<\/h3>\n<p>\u042d\u0442\u043e, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0441\u0430\u043c\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043d\u043e \u0431\u0435\u0437 \u043d\u0435\u0433\u043e \u043d\u0438\u043a\u0430\u043a!<\/p>\n<p>\u0412\u0441\u0435, \u0447\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0411\u0414 \u0438\u043b\u0438 \u043b\u044e\u0431\u044b\u043c\u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438 \u0441\u043b\u0443\u0436\u0431\u0430\u043c\u0438, \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0438\u043c\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u043c\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 CDI, \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u043e\u043a\u0430\u043c\u0438.\u00a0\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f\u00a0<code>mockito<\/code>\u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e:<\/p>\n<pre><code>@ExtendWith(MockitoExtension.class) public class SockShopResourceMockTest {      private List&lt;Socks> socksList = List.of(new Socks(1L, \"Model1\", 10.00),             new Socks(2L, \"Model2\", 20.00));      @InjectMocks     private SockShopResource sockShopResource;      @Mock     private ShoppingService shoppingService;      @BeforeEach     private void init() {         Mockito.lenient().doCallRealMethod().when(shoppingService).allSocks();     }      @Test     void allSocksTest() {         Mockito.doReturn(socksList).when(shoppingService).allSocks();          String response = sockShopResource.allSocks();         assertEquals(response, \"[{\\\"id\\\":1,\\\"model\\\":\\\"Model1\\\",\\\"price\\\":10.0},{\\\"id\\\":2,\\\"model\\\":\\\"Model2\\\",\\\"price\\\":20.0}]\");         Mockito.verifyNoMoreInteractions(shoppingService);      } }<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435,\u00a0<code>ShoppingService<\/code>\u044d\u0442\u043e \u043c\u043e\u043a, \u0438 \u043c\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c SockShopResource \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.\u00a0\u0422\u0430\u043a\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u043e, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d.<\/p>\n<h3>@HelidonTest<\/h3>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e, \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0433\u043b\u0443\u0431\u0438\u043c\u0441\u044f \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0433\u043e Helidon.<\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0439 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 &#8212; <code>@HelidonTest.<\/code>\u041e\u043d\u0430 \u0431\u0435\u0440\u0435\u0442 \u043d\u0430 \u0441\u0435\u0431\u044f \u0432\u0441\u0435 \u0437\u0430\u0431\u043e\u0442\u044b \u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u0432\u0441\u0435\u0433\u043e.<\/p>\n<pre><code class=\"java\">@HelidonTest public class TestSocksResource {      @Inject     WebTarget webTarget;      @Test     void testAllSocks(){          JsonArray jsonObject = webTarget.path(\"\/api\/shop\/allSocks\")                 .request()                 .get(JsonArray.class);          assertEquals(\"[{\\\"model\\\":\\\"Model1\\\",\\\"price\\\":10.0},{\\\"model\\\":\\\"Model2\\\",\\\"price\\\":20.0}]\",jsonObject.toString());     } } <\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u043d\u043e\u0439 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u043c\u044b \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c Helidon MP, \u0432\u0441\u0435 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 CDI \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0442\u0441\u044f.  \u0422\u0430\u043a \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.\u00a0\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u00a0<code>WebTarget<\/code>\u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0438\u0445 REST \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432.<\/p>\n<p>\u0421 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f\u043c\u0438, \u0442\u0430\u043a\u0438\u043c\u0438, \u043a\u0430\u043a \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"java\">@DisableDiscovery  @AddExtension (ConfigCdiExtension.class)  @AddBean (SocksTest.ConfiguredBean.class)  @AddConfig (key = \"test.message\", value = \"Socks!\")<\/code><\/pre>\n<p>&#8230; \u0442\u0435\u0441\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c!<\/p>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u044d\u0442\u0438\u0445 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u0431\u043b\u043e\u0433 \u043f\u043e\u0441\u0442\u0435\u00a0<a href=\"https:\/\/medium.com\/helidon\/testing-helidon-9df2ea14e22\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/medium.com\/helidon\/testing-helidon-9df2ea14e22<\/u><\/a><\/p>\n<h3>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Testcontainers<\/h3>\n<p><a href=\"https:\/\/www.testcontainers.org\/\" rel=\"noopener noreferrer nofollow\">Testcontainers<\/a> &#8212; \u044d\u0442\u043e \u043f\u043e-\u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u043c\u0443 \u0448\u0435\u0434\u0435\u0432\u0440\u0430\u043b\u044c\u043d\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u043d\u043e\u0432\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c.\u00a0\u0421 \u0438\u0445 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c Helidon, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430:<\/p>\n<pre><code class=\"java\">protected static final String NETWORK_ALIAS_APPLICATION = \"application\";  protected static final Network NETWORK = Network.newNetwork();  protected static final GenericContainer&lt;?> APPLICATION = new GenericContainer&lt;>(\"socks-shop:latest\")     .withExposedPorts(8080)     .withNetwork(NETWORK)     .withNetworkAliases(NETWORK_ALIAS_APPLICATION)     .withEnv(\"JAVA_OPTS\", \"-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true\")     .waitingFor(Wait.forHealthcheck());  static {   APPLICATION.start(); }<\/code><\/pre>\n<p>Generic Container \u0432\u043f\u043e\u043b\u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e.\u00a0\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u043e\u043a\u0435\u0440 \u043e\u0431\u0440\u0430\u0437\u0430 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u00a0<code>docker-maven-plugin<\/code>\u043e\u0442 Spotify:<\/p>\n<pre><code class=\"xml\">&lt;plugin>     &lt;groupId>com.spotify&lt;\/groupId>     &lt;artifactId>dockerfile-maven-plugin&lt;\/artifactId>     &lt;version>1.4.13&lt;\/version>     &lt;configuration>         &lt;repository>${project.build.finalName}&lt;\/repository<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-398587","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/398587","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=398587"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/398587\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=398587"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=398587"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=398587"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}