Help
RSS
API
Feed
Maltego
Contact
Domain > mail.itzap.com
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2026-02-22
107.180.116.246
(
ClassC
)
Port 443
HTTP/1.1 200 OKDate: Sun, 22 Feb 2026 03:20:22 GMTServer: ApacheX-Powered-By: PHP/7.2.34Link: https://itzap.com/wp-json/>; relhttps://api.w.org/Upgrade: h2,h2cConnection: UpgradeVary: Accept-EncodingTransfer-Encoding: chunkedContent-Type: text/html; charsetUTF-8 !DOCTYPE html>html langen>head> meta charsetUTF-8 /> meta nameviewport contentwidthdevice-width, initial-scale1.0> link relpingback hrefhttps://itzap.com/xmlrpc.php /> meta namerobots contentindex, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1 /> !-- This site is optimized with the Yoast SEO plugin v16.5 - https://yoast.com/wordpress/plugins/seo/ --> title>ITZap Development - Design patterns and libraries for quick application development/title> meta namedescription contentDesign patterns and libraries for quick application development /> link relcanonical hrefhttp://itzap.com/ /> link relnext hrefhttp://itzap.com/page/2/ /> meta propertyog:locale contenten_US /> meta propertyog:type contentwebsite /> meta propertyog:title contentITZap Development - Design patterns and libraries for quick application development /> meta propertyog:description contentDesign patterns and libraries for quick application development /> meta propertyog:url contenthttp://itzap.com/ /> meta propertyog:site_name contentITZap Development /> meta nametwitter:card contentsummary_large_image /> meta nametwitter:site content@a_vinokurov00 /> script typeapplication/ld+json classyoast-schema-graph>{@context:https://schema.org,@graph:{@type:WebSite,@id:http://itzap.com/#website,url:http://itzap.com/,name:ITZap Development,description:Design patterns and libraries for quick application development,potentialAction:{@type:SearchAction,target:http://itzap.com/?s{search_term_string},query-input:required namesearch_term_string},inLanguage:en},{@type:CollectionPage,@id:http://itzap.com/#webpage,url:http://itzap.com/,name:ITZap Development - Design patterns and libraries for quick application development,isPartOf:{@id:http://itzap.com/#website},description:Design patterns and libraries for quick application development,breadcrumb:{@id:http://itzap.com/#breadcrumb},inLanguage:en,potentialAction:{@type:ReadAction,target:http://itzap.com/}},{@type:BreadcrumbList,@id:http://itzap.com/#breadcrumb,itemListElement:{@type:ListItem,position:1,name:Home}}}/script> !-- / Yoast SEO plugin. -->link reldns-prefetch href//itzap.com />link reldns-prefetch href//fonts.googleapis.com />link reldns-prefetch href//s.w.org />link relalternate typeapplication/rss+xml titleITZap Development » Feed hrefhttps://itzap.com/feed/ />link relalternate typeapplication/rss+xml titleITZap Development » Comments Feed hrefhttps://itzap.com/comments/feed/ /> !-- This site uses the Google Analytics by MonsterInsights plugin v7.17.0 - Using Analytics tracking - https://www.monsterinsights.com/ --> script src//www.googletagmanager.com/gtag/js?idUA-149425613-1 typetext/javascript data-cfasyncfalse>/script> script typetext/javascript data-cfasyncfalse> var mi_version 7.17.0; var mi_track_user true; var mi_no_track_reason ; var disableStr ga-disable-UA-149425613-1; /* Function to detect opted out users */ function __gtagTrackerIsOptedOut() { return document.cookie.indexOf( disableStr + true ) > - 1; } /* Disable tracking if the opt-out cookie exists. */ if ( __gtagTrackerIsOptedOut() ) { windowdisableStr true; } /* Opt-out function */ function __gtagTrackerOptout() { document.cookie disableStr + true; expiresThu, 31 Dec 2099 23:59:59 UTC; path/; windowdisableStr true; } if ( undefined typeof gaOptout ) { function gaOptout() { __gtagTrackerOptout(); } } window.dataLayer window.dataLayer || ; if ( mi_track_user ) { function __gtagTracker() {dataLayer.push( arguments );} __gtagTracker( js, new Date() ); __gtagTracker( set, { developer_id.dZGIzZG : true, }); __gtagTracker( config, UA-149425613-1, { forceSSL:true,link_attribution:true, } ); window.gtag __gtagTracker; ( function () { /* https://developers.google.com/analytics/devguides/collection/analyticsjs/ */ /* ga and __gaTracker compatibility shim. */ var noopfn function () { return null; }; var newtracker function () { return new Tracker(); }; var Tracker function () { return null; }; var p Tracker.prototype; p.get noopfn; p.set noopfn; p.send function (){ var args Array.prototype.slice.call(arguments); args.unshift( send ); __gaTracker.apply(null, args); }; var __gaTracker function () { var len arguments.length; if ( len 0 ) { return; } var f argumentslen - 1; if ( typeof f ! object || f null || typeof f.hitCallback ! function ) { if ( send arguments0 ) { var hitConverted, hitObject false, action; if ( event arguments1 ) { if ( undefined ! typeof arguments3 ) { hitObject { eventAction: arguments3, eventCategory: arguments2, eventLabel: arguments4, value: arguments5 ? arguments5 : 1, } } } if ( typeof arguments2 object ) { hitObject arguments2; } if ( typeof arguments5 object ) { Object.assign( hitObject, arguments5 ); } if ( undefined ! typeof ( arguments1.hitType ) ) { hitObject arguments1; } if ( hitObject ) { action timing arguments1.hitType ? timing_complete : hitObject.eventAction; hitConverted mapArgs( hitObject ); __gtagTracker( event, action, hitConverted ); } } return; } function mapArgs( args ) { var gaKey, hit {}; var gaMap { eventCategory: event_category, eventAction: event_action, eventLabel: event_label, eventValue: event_value, nonInteraction: non_interaction, timingCategory: event_category, timingVar: name, timingValue: value, timingLabel: event_label, }; for ( gaKey in gaMap ) { if ( undefined ! typeof argsgaKey ) { hitgaMapgaKey argsgaKey; } } return hit; } try { f.hitCallback(); } catch ( ex ) { } }; __gaTracker.create newtracker; __gaTracker.getByName newtracker; __gaTracker.getAll function () { return ; }; __gaTracker.remove noopfn; __gaTracker.loaded true; window__gaTracker __gaTracker; } )(); } else { console.log( ); ( function () { function __gtagTracker() { return null; } window__gtagTracker __gtagTracker; windowgtag __gtagTracker; } )(); } /script> !-- / Google Analytics by MonsterInsights --> script typetext/javascript> window._wpemojiSettings {baseUrl:https:\/\/s.w.org\/images\/core\/emoji\/13.0.1\/72x72\/,ext:.png,svgUrl:https:\/\/s.w.org\/images\/core\/emoji\/13.0.1\/svg\/,svgExt:.svg,source:{concatemoji:https:\/\/itzap.com\/wp-includes\/js\/wp-emoji-release.min.js?ver5.7.14}}; !function(e,a,t){var n,r,o,ia.createElement(canvas),pi.getContext&&i.getContext(2d);function s(e,t){var aString.fromCharCode;p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,e),0,0);ei.toDataURL();return p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,t),0,0),ei.toDataURL()}function c(e){var ta.createElement(script);t.srce,t.defert.typetext/javascript,a.getElementsByTagName(head)0.appendChild(t)}for(oArray(flag,emoji),t.supports{everything:!0,everythingExceptFlag:!0},r0;ro.length;r++)t.supportsorfunction(e){if(!p||!p.fillText)return!1;switch(p.textBaselinetop,p.font600 32px Arial,e){caseflag:return s(127987,65039,8205,9895,65039,127987,65039,8203,9895,65039)?!1:!s(55356,56826,55356,56819,55356,56826,8203,55356,56819)&&!s(55356,57332,56128,56423,56128,56418,56128,56421,56128,56430,56128,56423,56128,56447,55356,57332,8203,56128,56423,8203,56128,56418,8203,56128,56421,8203,56128,56430,8203,56128,56423,8203,56128,56447);caseemoji:return!s(55357,56424,8205,55356,57212,55357,56424,8203,55356,57212)}return!1}(or),t.supports.everythingt.supports.everything&&t.supportsor,flag!or&&(t.supports.everythingExceptFlagt.supports.everythingExceptFlag&&t.supportsor);t.supports.everythingExceptFlagt.supports.everythingExceptFlag&&!t.supports.flag,t.DOMReady!1,t.readyCallbackfunction(){t.DOMReady!0},t.supports.everything||(nfunction(){t.readyCallback()},a.addEventListener?(a.addEventListener(DOMContentLoaded,n,!1),e.addEventListener(load,n,!1)):(e.attachEvent(onload,n),a.attachEvent(onreadystatechange,function(){completea.readyState&&t.readyCallback()})),(nt.source||{}).concatemoji?c(n.concatemoji):n.wpemoji&&n.twemoji&&(c(n.twemoji),c(n.wpemoji)))}(window,document,window._wpemojiSettings); /script> style typetext/css>img.wp-smiley,img.emoji { display: inline !important; border: none !important; box-shadow: none !important; height: 1em !important; width: 1em !important; margin: 0 .07em !important; vertical-align: -0.1em !important; background: none !important; padding: 0 !important;}/style> style classcustom-scrollbar typetext/css>.long_code { max-height: 400px; overflow-y: auto; overflow-x: hidden;}/style>link relstylesheet idwp-block-library-css hrefhttps://itzap.com/wp-includes/css/dist/block-library/style.min.css?ver5.7.14 typetext/css mediaall />link relstylesheet idcoblocks-frontend-css hrefhttps://itzap.com/wp-content/plugins/coblocks/dist/coblocks-style.css?ver4eb0a03e505406b9570c790300e41d08 typetext/css mediaall />link relstylesheet idfont-awesome-css hrefhttps://itzap.com/wp-content/plugins/contact-widgets/assets/css/font-awesome.min.css?ver4.7.0 typetext/css mediaall />link relstylesheet idmd_github-css hrefhttps://itzap.com/wp-content/plugins/markdown-github/css/md-github.css?ver5.7.14 typetext/css mediaall />link relstylesheet idcodemirror-blocks--css hrefhttps://itzap.com/wp-content/plugins/wp-codemirror-block/assets/blocks/blocks.style.build.min.css?ver1601953897 typetext/css mediaall />link relstylesheet idmalihu-custom-scrollbar-css-css hrefhttps://itzap.com/wp-content/plugins/custom-scrollbar/asset/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.min.css?ver5.7.14 typetext/css mediaall />link relstylesheet idnormalize-css hrefhttps://itzap.com/wp-content/themes/espresso-programmer/normalize.css?ver5.7.14-1570227395 typetext/css mediaall />link relstylesheet idopen-sans-google-font-css hrefhttps://fonts.googleapis.com/css?familyOpen+Sans&ver5.7.14 typetext/css mediaall />link relstylesheet idsource-code-pro-google-font-css hrefhttps://fonts.googleapis.com/css?familySource+Code+Pro&ver5.7.14 typetext/css mediaall />link relstylesheet idespresso-programmer-style-css hrefhttps://itzap.com/wp-content/themes/espresso-programmer/style.css?ver5.7.14-1570227395 typetext/css mediaall />link relstylesheet idwpcw-css hrefhttps://itzap.com/wp-content/plugins/contact-widgets/assets/css/style.min.css?ver1.0.1 typetext/css mediaall />link relstylesheet idtablepress-default-css hrefhttps://itzap.com/wp-content/plugins/tablepress/css/default.min.css?ver1.13 typetext/css mediaall />script typetext/javascript idmonsterinsights-frontend-script-js-extra>/* !CDATA */var monsterinsights_frontend {js_events_tracking:true,download_extensions:doc,pdf,ppt,zip,xls,docx,pptx,xlsx,inbound_paths:{\path\:\\\\/go\\\/\,\label\:\affiliate\},{\path\:\\\\/recommend\\\/\,\label\:\affiliate\},home_url:https:\/\/itzap.com,hash_tracking:false,ua:UA-149425613-1};/* > *//script>script typetext/javascript srchttps://itzap.com/wp-content/plugins/google-analytics-for-wordpress/assets/js/frontend-gtag.min.js?ver7.17.0 idmonsterinsights-frontend-script-js>/script>script typetext/javascript srchttps://itzap.com/wp-includes/js/jquery/jquery.min.js?ver3.5.1 idjquery-core-js>/script>script typetext/javascript srchttps://itzap.com/wp-includes/js/jquery/jquery-migrate.min.js?ver3.3.2 idjquery-migrate-js>/script>link relhttps://api.w.org/ hrefhttps://itzap.com/wp-json/ />link relEditURI typeapplication/rsd+xml titleRSD hrefhttps://itzap.com/xmlrpc.php?rsd />link relwlwmanifest typeapplication/wlwmanifest+xml hrefhttps://itzap.com/wp-includes/wlwmanifest.xml /> meta namegenerator contentWordPress 5.7.14 />script async srchttps://www.googletagmanager.com/gtag/js?idUA-149425613-1 typetext/javascript>/script>script typetext/javascript>window.dataLayer window.dataLayer || ;function gtag(){dataLayer.push(arguments);}gtag(js, new Date());gtag(config, UA-149425613-1);/script>/head>body classhome blog>div idpage>header idheader> nav classblog-header> div classblog-home> a hrefhttps://itzap.com/ titleITZap Development relhome> img src altITZap Development classblog-logo /> /a> /div> div classblog-info> div classblog-name> a hrefhttps://itzap.com/> ITZap Development /a> /div> div classblog-description>Design patterns and libraries for quick application development/div> /div> /nav>/header>nav idmenu-primary classmenu>ul idmenu-primary-items classmenu-items>li idmenu-item-15 classmenu-item>a hrefhttp://itzap.com>Home/a>/li>li idmenu-item-13 classmenu-item>a hrefhttps://itzap.com/about_aleksey_vinokurov/>About Me/a>/li>li idmenu-item-12 classmenu-item>a hrefhttps://itzap.com/contact/>Contact Me/a>/li>/ul>/nav>div classposts rolemain> article classpost-261 post type-post status-publish format-standard hentry category-code category-java category-spring itemscope itemtypehttp://schema.org/Article> header classpost-info> h1> a hrefhttps://itzap.com/how-to-access-http-request-body-object-using-spring-handlermethodargumentresolver/> How to access HTTP request body object using spring HandlerMethodArgumentResolver /a> /h1> time classpost-time datetime2020-03-03 itempropdatePublished> March 3, 2020 /time> /header> div classpost-content itemproparticleBody> h2>Scenario/h2>p>Spring framework provides mechanism for binding controller method parameters to custom model. Here is a very good article on how to implement custom data binding a relnoreferrer noopener aria-label (opens in a new tab) hrefhttps://www.baeldung.com/spring-mvc-custom-data-binder target_blank>https://www.baeldung.com/spring-mvc-custom-data-binder/a> During data binding there might be a need to access HTTP request body. /p>h2>Solution/h2>p>HTTP request body is hidden in the strong>ModelAndViewContainer/strong> object that spring provides to the argument resolver. Here is a code example:/p>div classwp-block-codemirror-blocks-code-block code-block long_code>pre classCodeMirror data-setting{"mode":"clike","mime":"text/x-java","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"className":"long_code","language":"Java","modeName":"java"}>public class MyContextArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(@Nullable MethodParameter methodParameter) { return methodParameter ! null && methodParameter.getParameterAnnotation(MyContext.class) ! null; } @Override public Object resolveArgument(@Nullable MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, @Nullable NativeWebRequest nativeWebRequest, return toContext(modelAndViewContainer); } private MyContext toContext(ModelAndViewContainer modelAndViewContainer) { if (modelAndViewContainer null) { return MyContext.builder().build(); } MyContext.Builder builder MyContext.builder(); modelAndViewContainer.getModel().forEach((k, v) -> { if (v instanceof BindingResult) { BindingResult result (BindingResult) v; if (result.getTarget() instanceof Map) { // plain map builder .setPropertyOne(((Map<?, ?>) result.getTarget()).get("propertyOne")) .setPropertyTwo(((Map<?, ?>) result.getTarget()).get("propertyTwo")); } else if (result.getTarget() instanceof MyRequest) { // handle MyRequest request builder .setPropertyOne(((MyRequest) result.getTarget()).getpropertyOne()) .setPropertyTwo(((MyRequest) result.getTarget()).getpropertyTwo()); } } }); return builder.builder(); } }/pre>/div>p>All details about setting up method argument resolver are omitted and the focus is on the strong>toContext/strong> function that demonstrates how to get request body from strong>ModelAndViewContainer/strong>. /p> /div> /article> article classpost-252 post type-post status-publish format-standard hentry category-bug-of-the-day category-code category-java category-spring-boot category-spring-cloud category-zuul itemscope itemtypehttp://schema.org/Article> header classpost-info> h1> a hrefhttps://itzap.com/zuul-useseparatethreadpools-and-rejectedexecutionexception/> Zuul useSeparateThreadPools and RejectedExecutionException /a> /h1> time classpost-time datetime2020-01-22 itempropdatePublished> January 22, 2020 /time> /header> div classpost-content itemproparticleBody> h3>Scenario/h3>p>spring-cloud/spring-boot application is using zuul API gateway to route client requests. Here is zuul config snippet /p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"lua","mime":"text/x-lua","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Lua","modeName":"lua"}>zuul.ribbonIsolationStrategyTHREADzuul.threadPool.useSeparateThreadPoolstrueribbon.eureka.enabled false# sevices.../pre>/div>p>Invoking service APIs through zuul gateway resulted in HTTP 500 response that looked something like this:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"javascript","mime":"application/json","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"JSON","modeName":"json"}>{ "timestamp": "2019-12-18T21:37:10.168+0000", "status": 500, "error": "Internal Server Error", "message": "REJECTED_THREAD_EXECUTION"}/pre>/div>p>Interesting part of this response is strong>REJECTED_THREAD_EXECUTION/strong>. None of the services were reporting this message. After looking deeper, the Zuul log showed this error/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"slim","mime":"text/x-slim","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Slim","modeName":"slim"}>Caused by: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@3b17817e rejected from java.util.concurrent.ThreadPoolExecutor@67f89c35Running, pool size 10, active threads 10, queued tasks 0, completed tasks 2535368 at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063) ~?:1.8.0_212 at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830) ~?:1.8.0_212/pre>/div>h3>Solution/h3>p>After realizing that exception is in the zuul log it was a matter of finding the right properties to configure services thread pools. By default, zuul was using 10 threads with the max thread count set to 10. To change this default across all services set these properties:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"lua","mime":"text/x-lua","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Lua","modeName":"lua"}># defualt threadpool confighystrix.threadpool.default.coreSize 150hystrix.threadpool.default.maximumSize 150/pre>/div>p>It is also possible to configure thread pools for each service that zuul is routing to. For example:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"lua","mime":"text/x-lua","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Lua","modeName":"lua"}>zuul.routes.first.urlfirstServiceIdzuul.routes.second.urlsecondServiceIdhystrix.threadpool.firstServiceId.coreSize 150hystrix.threadpool.firstServiceId.maximumSize 150hystrix.threadpool.secondServiceId.coreSize 50hystrix.threadpool.secondServiceId.maximumSize 150/pre>/div> /div> /article> article classpost-246 post type-post status-publish format-standard hentry category-bug-of-the-day category-code category-java category-spring-boot itemscope itemtypehttp://schema.org/Article> header classpost-info> h1> a hrefhttps://itzap.com/factory-method-textencryptor-threw-exception/> Factory method ‘textEncryptor’ threw exception /a> /h1> time classpost-time datetime2019-12-07 itempropdatePublished> December 7, 2019 /time> /header> div classpost-content itemproparticleBody> h3>Scenario/h3>p>Suppose you are working on multiple Spring Boot/Spring Cloud projects that are using the spring cloud config server. You setup property encryption for the spring-cloud config. The encryption key is sored in your local profile as an environment variable code>ENCRYPT_KEY/code>. Then, you switch to work on another spring-boot/spring-cloud project that does not use spring config server and have code>spring-cloud-context/code> as a dependency. When you run this project you get the following exception stack trace:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"slim","mime":"text/x-slim","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Slim","modeName":"slim"}>Caused by: java.lang.NullPointerException: null at org.springframework.cloud.context.encrypt.EncryptorFactory.create(EncryptorFactory.java:54) at org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration$RsaEncryptionConfiguration.textEncryptor(EncryptionBootstrapConfiguration.java:83) at org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration$RsaEncryptionConfiguration$$EnhancerBySpringCGLIB$$c1a972bf.CGLIB$textEncryptor$0(<generated>) at org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration$RsaEncryptionConfiguration$$EnhancerBySpringCGLIB$$c1a972bf$$FastClassBySpringCGLIB$$4d33eb7b.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) at org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration$RsaEncryptionConfiguration$$EnhancerBySpringCGLIB$$c1a972bf.textEncryptor(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ... 31 common frames omitted/pre>/div>h3>Diagnostic/h3>p>This is actually a spring bug! Another way to provide the encryption key to the config server is to use -Dencrypt.key123 system property. If you do it this way everything is working fine. The problem only arises when the environment variable code>ENCRYPT_KEY/code> is used. The root cause is in:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"clike","mime":"text/x-java","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Java","modeName":"java"}>org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration.KeyCondition/pre>/div>p>This condition bean determines whether spring will initialize code>TextEncryptor/code> class or not. When spring detects code>ENCRYPT_KEY/code> environment variable the code>TextEncryptor/code> class gets created. It uses code>KeyProperties/code> to initialize encryptor. If code>-Dencrypt.key123/code> is provided then code>KeyProperties/code> is initialized with the key provided as a system property. If code>ENCRYPT_KEY/code> environment variable is found code>KeyProperties/code> are not initialized and the code>key/code> member is code>null/code>. /p>h3>Solution/h3>p>Remove code>ENCRYPT_KEY/code> property from the environment prior to running spring boot application. The problem is fixed./p> /div> /article> article classpost-237 post type-post status-publish format-standard hentry category-code category-executable-jar category-java category-jersey category-swagger tag-embedded tag-jersey tag-rest-api tag-swagger tag-swaggerui tag-tomcat itemscope itemtypehttp://schema.org/Article> header classpost-info> h1> a hrefhttps://itzap.com/swagger-ui-in-jersey-api/> Swagger UI in Jersey Application /a> /h1> time classpost-time datetime2019-12-05 itempropdatePublished> December 5, 2019 /time> /header> div classpost-content itemproparticleBody> h3>Vision Statement/h3>p>Provide a library that can serve swagger UI in Jersey application. Inspiration for this library was the a relnoreferrer noopener aria-labelSpringFox Swagger UI (opens in a new tab) hrefhttps://github.com/springfox/springfox/tree/master/springfox-swagger-ui target_blank>SpringFox Swagger UI/a> project that works with spring boot g classgr_ gr_5 gr-alert gr_gramm gr_inline_cards gr_disable_anim_appear Grammar multiReplace id5 data-gr-id5>application/g>./p>h3>Use Case/h3>p>Suppose you have a runnable Jar Jersey REST API application with Open API annotations and would like to provide a swagger UI for API consumers to learn and play with your APIs. Swagger UI comes as a set of static Javascript files that need to be included in your application. In addition, you need to configure a web context that will serve swagger UI pages. By including strong>a hrefhttps://github.com/avinokurov/itzap-jerseyswagger-starter>g classgr_ gr_6 gr-alert gr_spell gr_inline_cards gr_disable_anim_appear ContextualSpelling ins-del multiReplace id6 data-gr-id6>itzap/g>-jerseyswagger.jar/a> /strong>in your project you will get an endpoint that will load functional Swagger UI with your API definitions./p>h3>Implementation Details/h3>p>Here is the code that starts embedded Tomcat in the project that I described in my previous g classgr_ gr_17 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling multiReplace id17 data-gr-id17>post /g>a relnoreferrer noopener aria-labelitzap-message (opens in a new tab) hrefhttp://itzap.com/itzap-jersey-embedded-tomcat-hk2-executable-jar-docker/ target_blank>g classgr_ gr_3 gr-alert gr_spell gr_inline_cards gr_disable_anim_appear ContextualSpelling ins-del multiReplace id3 data-gr-id3>itzap/g>-message/a>. I modified it to use Open API annotations and include swagger UI./p>div classwp-block-codemirror-blocks-code-block code-block long_code>pre classCodeMirror data-setting{"mode":"clike","mime":"text/x-java","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"className":"long_code","language":"Java","modeName":"java"}>private static void start() throws Exception { String contextPath ""; String appBase "."; String port System.getenv("PORT"); if (port null || port.isEmpty()) { port "8025"; } Tomcat tomcat new Tomcat(); tomcat.setPort(Integer.parseInt(port)); tomcat.getHost().setAppBase(appBase); Context context tomcat.addWebapp(contextPath, appBase); Tomcat.addServlet(context, "jersey-container-servlet", new ServletContainer(resourceConfig())); context.addServletMappingDecoded(UDecoder.URLDecode("/v1/itzap/message/*", Charset.defaultCharset()), "jersey-container-servlet"); SwaggerContext.addSwaggerServlet(tomcat, context, ConfigBuilder.builder(ConfigType.TYPE_SAFE) .build() .getConfig("swagger"), EmailApplication.class); tomcat.getConnector(); tomcat.start(); tomcat.getServer().await(); }/pre>/div>p>The code to notice here is:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"clike","mime":"text/x-java","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Java","modeName":"java"}>SwaggerContext.addSwaggerServlet(tomcat, context, ConfigBuilder.builder(ConfigType.TYPE_SAFE) .build() .getConfig("swagger"), EmailApplication.class);/pre>/div>p>That all you need to do to add swagger UI to the REST API application./p>p>There are a few properties that need to be added to the project configuration./p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"properties","mime":"text/x-properties","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Properties files","modeName":"properties"}>swagger.package"com.itzap"swagger.apiBaseUrl"http://${email.host}/v1/itzap/message/"/pre>/div>p>Now you can start the project code>java -jar message-impl/target/message-impl-0.0.1-SNAPSHOT.jar/code> and navigate your browser to/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"sas","mime":"text/x-sas","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"SAS","modeName":"sas"}>http://localhost:8025/api/v1/swagger/pre>/div>figure classwp-block-image size-large>img loadinglazy width1024 height502 srchttp://itzap.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-05-at-12.49.50-AM-1024x502.png alt classwp-image-242 srcsethttp://itzap.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-05-at-12.49.50-AM-1024x502.png 1024w, http://itzap.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-05-at-12.49.50-AM-300x147.png 300w, http://itzap.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-05-at-12.49.50-AM-768x376.png 768w, http://itzap.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-05-at-12.49.50-AM-1536x753.png 1536w, http://itzap.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-05-at-12.49.50-AM-2048x1004.png 2048w, http://itzap.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-05-at-12.49.50-AM-700x343.png 700w sizes(max-width: 1024px) 100vw, 1024px />/figure>h3>Readme/h3>div idfile classmd data-pathREADME.md>article classmarkdown-body entry-content container-lg itemproptext>div classmarkdown-heading dirauto>h1 classheading-element dirauto>itzap-jerseyswagger/h1>a iduser-content-itzap-jerseyswagger classanchor aria-labelPermalink: itzap-jerseyswagger href#itzap-jerseyswagger>svg classocticon octicon-link viewBox0 0 16 16 version1.1 width16 height16 aria-hiddentrue>path dm7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z>/path>/svg>/a>/div>p dirauto>strong>itzap-jerseyswagger/strong> library is designed to provide swagger UI endpoint to the Jersey REST API application./p>div classmarkdown-heading dirauto>h2 classheading-element dirauto>Usage/h2>a iduser-content-usage classanchor aria-labelPermalink: Usage href#usage>svg classocticon octicon-link viewBox0 0 16 16 version1.1 width16 height16 aria-hiddentrue>path dm7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z>/path>/svg>/a>/div>p dirauto>Include strong>itzap-jerseyswagger/strong> dependency to your project./p>div classhighlight highlight-text-xml notranslate position-relative overflow-auto dirauto data-snippet-clipboard-copy-content<dependency> <groupId>com.itzap</groupId> <artifactId>itzap-jerseyswagger</artifactId> <version>0.0.1-SNAPSHOT</version></dependency>>pre><span classpl-ent>dependency/span>> <span classpl-ent>groupId/span>>com.itzap</span classpl-ent>groupId/span>> <span classpl-ent>artifactId/span>>itzap-jerseyswagger</span classpl-ent>artifactId/span>> <span classpl-ent>version/span>>0.0.1-SNAPSHOT</span classpl-ent>version/span>></span classpl-ent>dependency/span>>/pre>/div>p dirauto>add the following properties to the application config file/p>div classhighlight highlight-source-ini notranslate position-relative overflow-auto dirauto data-snippet-clipboard-copy-contentswagger.package"com.itzap"swagger.apiBaseUrl"http://${email.host}/v1/itzap/message/">pre>span classpl-k>swagger.package/span>span classpl-s>span classpl-pds>/span>com.itzapspan classpl-pds>/span>/span>span classpl-k>swagger.apiBaseUrl/span>span classpl-s>span classpl-pds>/span>http://${email.host}/v1/itzap/message/span classpl-pds>/span>/span>/pre>/div>p dirauto>The following code will add swaggerUI artifacts and context/p>div classhighlight highlight-source-java notranslate position-relative overflow-auto dirauto data-snippet-clipboard-copy-contentSwaggerContext.addSwaggerServlet(tomcat, context, ConfigBuilder.builder(ConfigType.TYPE_SAFE) .build() .getConfig("swagger"), EmailApplication.class);>pre>span classpl-smi>SwaggerContext/span>.span classpl-en>addSwaggerServlet/span>(span classpl-s1>tomcat/span>, span classpl-s1>context/span>, span classpl-smi>ConfigBuilder/span>.span classpl-en>builder/span>(span classpl-smi>ConfigType/span>.span classpl-c1>TYPE_SAFE/span>) .span classpl-en>build/span>() .span classpl-en>getConfig/span>(span classpl-s>swagger/span>), span classpl-smi>EmailApplication/span>.span classpl-k>class/span>);/pre>/div>div classmarkdown-heading dirauto>h3 classheading-element dirauto>How To Build/h3>a iduser-content-how-to-build classanchor aria-labelPermalink: How To Build href#how-to-build>svg classocticon octicon-link viewBox0 0 16 16 version1.1 width16 height16 aria-hiddentrue>path dm7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z>/path>/svg>/a>/div>ul dirauto>li>Clone the following projects:ul dirauto>li>code>git clone git@github.com:avinokurov/itzap-parent.git/code>/li>li>code>git clone git@github.com:avinokurov/itzap-common.git/code>/li>/ul>/li>li>Build all projectsul dirauto>li>code>cd itzap-parent && mvn clean install/code>/li>li>code>cd ../itzap-common && mvn clean install/code>/li>/ul>/li>/ul>p dirauto>Visit my a hrefhttp://itzap.com/swagger-ui-in-jersey-api/ relnofollow>ITZap blog/a> to read more about this project./p>/article>/div>h3>Code/h3>p>Complete implementation can be found here:/p>div classmarkdown-github> div classmarkdown-github-labels> label classgithub-link> a hrefhttps://github.com/avinokurov/itzap-jerseyswagger-starter target_blank>Check it out on github/a> label classgithub-last-update> Last updated: 30/10/2020 00:57:18/label> /label> /div> /div> /div> /article> article classpost-225 post type-post status-publish format-standard hentry category-code category-java category-pattern tag-builder tag-immutable tag-java itemscope itemtypehttp://schema.org/Article> header classpost-info> h1> a hrefhttps://itzap.com/java-builder-pattern-with-shared-state/> Builder Pattern with Shared State /a> /h1> time classpost-time datetime2019-11-09 itempropdatePublished> November 9, 2019 /time> /header> div classpost-content itemproparticleBody> h3>Vision Statement/h3>p>Immutable POJOs are key to bug-free programs. It is not straight forward to write immutable POJOs in Java. Builder pattern comes handy to solve this problem by separating getters and setters. The problem with the Builder pattern in java is the need to duplicate POJO properties. The purpose of this solution is to minimize the downside of the Builder pattern in java by separating the state into a separate class./p>h3>Use Case/h3>p>Suppose we have a code>User/code> POJO like this:/p>div classwp-block-codemirror-blocks-code-block code-block long_code>pre classCodeMirror cm-s-idea data-setting{"mode":"clike","mime":"text/x-java","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"className":"long_code","language":"Java","modeName":"java"}>public class User { private final String lastName; private final String firstName; private User(Builder builder) { this.lastName builder.lastName; this.firstName builder.firstName; } public String getLastName() { return this.lastName; } public String getFirstName() { return this.firstName; } public static class Builder { private String lastName; private String firstName; public Builder setLastName(String lastName) { this.lastName lastName; return this; } public Builder setFirstName(String firstName) { this.firstName firstName; return this; } public User build() { return new User(this); } } public static Builder builder() { return new Builder(); }}/pre>/div>p>The problem with the above solution is that code>lastName/code> and code>firstName/code> attributes need to be repeated for both builder and POJO itself. /p>h3>Solution/h3>p>To address this issue we can try to separate attributes into a separate code>State/code> class./p>div classwp-block-codemirror-blocks-code-block code-block long_code>pre classCodeMirror cm-s-idea data-setting{"mode":"clike","mime":"text/x-java","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"className":"long_code","language":"Java","modeName":"java"}>public class User { private static class State { private String lastName; private String firstName; } private final State state; private User(Builder builder) { this.state builder.state; } public String getLastName() { return this.state.lastName; } public String getFirstName() { return this.state.firstName; } public static class Builder { private final State state new State(); public Builder setLastName(String lastName) { this.state.lastName lastName; return this; } public Builder setFirstName(String firstName) { this.state.firstName firstName; return this; } public User build() { return new User(this); } public static Builder from(User user) { return User.builder() .setLastName(user.getLastName()) .setFirstName(user.getFirstName()); } } public static Builder builder() { return new Builder(); }}/pre>/div>h3>Bonus for IntelliJ Users/h3>p>IntelliJ’s generate Getter/Setter feature cannot be used effectively when attributes of the POJO are factored out into a separate State. Luckily, IntelliJ provides the ability to customize generators. Here is an example of a possible custom Getter/Setter generator scripts./p>h4>Getter/h4>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"mllike","mime":"text/x-fsharp","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"F#","modeName":"fsharp"}>#if($field.modifierStatic)static ###end$field.type ###set($name $StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project))))#if ($field.boolean && $field.primitive) is###else get###end${name}() { return this.state.$field.name;}/pre>/div>h4>Setter/h4>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"mllike","mime":"text/x-fsharp","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"F#","modeName":"fsharp"}>#set($paramName $helper.getParamName($field, $project))public ###if($field.modifierStatic)static void ###else Builder ###endset$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project)))($field.type $paramName) {#if ($field.name $paramName) #if (!$field.modifierStatic) this.state.## #else $this.state.## #end#end$field.name $paramName;#if(!$field.modifierStatic)return this;#end}/pre>/div>p>Navigate to the State class and generate Getters/Setters. Then copy getters to the POJO and setters to the builder. A small extra step but save a lot of boilerplate code./p> /div> /article> article classpost-205 post type-post status-publish format-standard hentry category-code category-ebean category-java category-rxjava category-sql tag-dao tag-ebean tag-java tag-rxjava tag-schema tag-sql itemscope itemtypehttp://schema.org/Article> header classpost-info> h1> a hrefhttps://itzap.com/sql-database-with-flexible-schema/> SQL Database With Flexible Schema /a> /h1> time classpost-time datetime2019-11-08 itempropdatePublished> November 8, 2019 /time> /header> div classpost-content itemproparticleBody> h3>Vision Statement/h3>p>NoSQL databases are dominating enterprise systems. One reason is that they do not require precise data schema and can deal with new data without triggering massive changes. The idea is to achieve schema flexibility with the typical SQL database like PostgreSQL or MySql. In general, NoSQL databases require some key/index/primary fields to enable fast lookups. If we preserve the concept of necessary fields and store the rest of the document in the JSON text field we can accomplish similar flexibility with the plain old SQL database./p>h3>Use Case/h3>p>Imagine some code>users/code> table where fields like code>username/code> and code>email/code> are required to identify a user, but user attributes like code>phone/code>, code>lastName/code>, code>firstName/code> can be just stored as part of the user record./p>h3>Implementation Details/h3>p>Here is the database schema for the above use case using H2 Java in-memory database:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"sql","mime":"text/x-sql","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"SQL","modeName":"sql"}>drop table if exists users;create table users( id bigint NOT NULL auto_increment, username varchar(50) not null, password varchar(255) not null, enabled boolean not null, email varchar(255) not null, object varchar(4048) NOT NULL DEFAULT {}, CONSTRAINT pk_users PRIMARY KEY (id));/pre>/div>p>In this example, application key fields defined as typical SQL schema and the rest of the document is stored in the code>object/code> field. Now, all we need to do is merge key fields into a final object. I used a relnoreferrer noopener aria-labelebean (opens in a new tab) hrefhttps://ebean.io/docs/ target_blank>ebean/a> ORM library to implement database connectivity and statement execution and command/reactive design pattern explained in my a hrefhttp://itzap.com/itzap-rxjava-reactive-programming/>RxJava/a> post to implement DAO layer./p>h3>Model/h3>p>code>itzap-ebeans/code> project implements this idea and contains an example code>UserDao/code> implementation. Simple user model looks like this:/p>div classwp-block-codemirror-blocks-code-block code-block long_code>pre classCodeMirror cm-s-idea data-setting{"mode":"clike","mime":"text/x-java","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"className":"long_code","language":"Java","modeName":"java"}>@JsonDeserialize(builder User.Builder.class)public class User extends Auditable { private final String lastName; private final String firstName; private final String email; private final String phone; @JsonProperty("enabled") private final Boolean enabled; private final String username; @JsonIgnore private final String password; public User(Builder builder) { super(builder); this.lastName builder.lastName; this.firstName builder.firstName; this.email builder.email; this.phone builder.phone; this.enabled builder.enabled; this.username builder.username; this.password builder.password; } public String getLastName() { return lastName; } public String getFirstName() { return firstName; } public String getEmail() { return email; } public String getPhone() { return phone; } public Boolean getEnabled() { return enabled; } public String getUsername() { return username; } public String getPassword() { return password; } @Override public String toString() { return MoreObjects.toStringHelper(this.getClass()) .add("lastName", lastName) .add("email", email) .add("username", username) .toString(); } @JsonPOJOBuilder(withPrefix "set") @JsonIgnoreProperties(ignoreUnknown true) public static class Builder extends Auditable.Builder<User, User.Builder> { private String lastName; private String firstName; private String email; private String phone; private Boolean enabled; private String username; private String password; public Builder() { } @Override protected Builder getThis() { return this; } public Builder setLastName(String lastName) { this.lastName lastName; return this; } public Builder setFirstName(String firstName) { this.firstName firstName; return this; } public Builder setEmail(String email) { this.email email; return this; } public Builder setPhone(String phone) { this.phone phone; return this; } public Builder setEnabled(Boolean enabled) { this.enabled enabled; return this; } public Builder setUsername(String username) { this.username username; return this; } public Builder setPassword(String password) { this.password password; return this; } @Override public Builder merge(User org) { Builder bld super.merge(org) .setEmail(StringUtils.defaultIfBlank(this.email, org.getEmail())) .setEnabled(ObjectUtils.defaultIfNull(this.enabled, org.getEnabled())) .setLastName(StringUtils.defaultIfBlank(this.lastName, org.getLastName())) .setUsername(StringUtils.defaultIfBlank(this.username, org.getUsername())) .setFirstName(StringUtils.defaultIfBlank(this.firstName, org.getFirstName())) .setPassword(StringUtils.defaultIfBlank(this.password, org.getPassword())) .setPhone(StringUtils.defaultIfBlank(this.phone, org.getPhone())); return bld; } @Override public User build() { return new User(this); } } public static Builder from(User user) { Builder builder new Builder(); BeanUtils.copyProperties(user, builder); return builder; } public static Builder builder() { return new Builder(); }}/pre>/div>p>Note all the Json annotations that enable serialization/deserialization of the model and code>merge/code> method that provides rules for merging database and Json objects./p>h3>Dao Implementation/h3>p>Dao layer implemented using two base commands: code>ListBaseEbeanCommand/code> and code>BaseBulkEbeanCommand/code>. code>ListBaseEbeanCommand/code> is the base command for all select operations and code>BaseBulkEbeanCommand/code> is the base command for all Insert/Update/Delete operations. Base commands operate using code>EbeanHandler/code> and report exceptions using code>EbeanErrorHandler/code>. Complete DAO implementation looks like this:/p>div classwp-block-codemirror-blocks-code-block code-block long_code>pre classCodeMirror cm-s-idea data-setting{"mode":"clike","mime":"text/x-java","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"className":"long_code","language":"Java","modeName":"java"}>public class UserDao extends AbstractServiceDao { private static final String SELECT_ALL_USERS "select * from users"; private static final String WHERE_USER " where username:username"; private static final String WHERE_USER_ID " where id:id"; private static final String ADD_USER "INSERT INTO public.users(" + " username, password, enabled, email, object)" + " VALUES (:username, :password, :enabled, :email, :object)"; private static final String UPDATE_USER "UPDATE public.users " + " SET username:username, password:password, enabled:enabled, email:email, object:object" + " WHERE id:id"; private static final String DELETE_USER "DELETE FROM users WHERE id:id"; public UserDao(Servers.Server server) { super(server); } public Observable<User> getUsers() { return new SelectUsersCommand() .toObservable() .flatMap(Observable::fromIterable); } public Observable<User> getUserByName(String name) { return new SelectUsersCommand() .setName(name) .toObservable() .map(users -> users.get(0)); } public Observable<User> getUser(Long userId) { return new SelectUsersCommand() .setUserId(userId) .toObservable() .map(users -> users.get(0)); } public Observable<Integer> addUser(User user) { return new BaseBulkEbeanCommand<BaseBulkEbeanCommand>("cmd-addUser-cmd", new UserHandler(user)) { @Override protected BaseBulkEbeanCommand getThis() { return this; } @Override protected SqlUpdate createSql() { return server.getServer().createSqlUpdate(ADD_USER); } }.toObservable(); } public Observable<Integer> updateUser(Long userId, User user) { return new SelectUsersCommand() .setName(user.getUsername()) .toObservable() .flatMap(orgUser -> new BaseBulkEbeanCommand<BaseBulkEbeanCommand>("cmd-updateUser-cmd", new UserHandler(userId, user, orgUser.get(0))) { @Override protected BaseBulkEbeanCommand getThis() { return this; } @Override protected SqlUpdate createSql() { return server.getServer().createSqlUpdate(UPDATE_USER); } }.toObservable()); } public Observable<Integer> deleteUser(Long id) { return new BaseBulkEbeanCommand<BaseBulkEbeanCommand>("cmd-deleteUser-cmd", new DeleteEbeanHandler<>(QueryParameter.id(id))) { @Override protected BaseBulkEbeanCommand getThis() { return this; } @Override protected SqlUpdate createSql() { return server.getServer().createSqlUpdate(DELETE_USER); } }.toObservable(); } class UserHandler extends AbstractAuditableHandler<User, User.Builder> { UserHandler(User user) { this(null, user, User.builder().build()); } UserHandler(Long userId, User user, User dbUser) { super(userId, user, dbUser); } @Override protected User.Builder rowProperties(SqlUpdate updateQuery, User user) { updateQuery.setParameter("username", StringUtils.defaultIfBlank(user.getUsername(), orgObject.getUsername())); String pass getPassword(user); if (StringUtils.isBlank(pass)) { updateQuery.setParameter("password", orgObject.getPassword()); } else { updateQuery.setParameter("password", pass); } updateQuery.setParameter("enabled", ObjectUtils.defaultIfNull(user.getEnabled(), orgObject.getEnabled())); updateQuery.setParameter("email", StringUtils.defaultIfBlank(user.getEmail(), orgObject.getEmail())); return audibalBuilder(user, User.from(user)); } } private static String getPassword(User user) { return user.getPassword(); } private static User.Builder fromRow(SqlRow row, User user) { return User.from(user) .setUsername(row.getString("username")) .setEmail(row.getString("email")) .setEnabled(row.getBoolean("enabled")) .setPassword(row.getString("password")); } class SelectUsersCommand extends ListBaseEbeanCommand<User, SelectUsersCommand> { private String name; private Long userId; public SelectUsersCommand setName(String name) { this.name name; return getThis(); } public SelectUsersCommand setUserId(Long userId) { this.userId userId; return this; } SelectUsersCommand() { super("cmd-get-users", new AbstractSelectListEbeanHandler<User, User.Builder>(User.class) { @Override protected User.Builder from(SqlRow row, User user) { return fromRow(row, user); } }); } @Override protected SelectUsersCommand getThis() { return this; } @Override protected SqlQuery createSql() { String sql SELECT_ALL_USERS; if (StringUtils.isNotBlank(this.name)) { sql sql + WHERE_USER; } else if (this.userId ! null) { sql sql + WHERE_USER_ID; } SqlQuery qry server.getServer().createSqlQuery(sql); if (StringUtils.isNotBlank(this.name)) { qry.setParameter("username", this.name); } else if (this.userId ! null) { qry.setParameter("id", this.userId); } return qry; } }}/pre>/div>h3>Readme/h3>div idfile classmd data-pathREADME.md>article classmarkdown-body entry-content container-lg itemproptext>div classmarkdown-heading dirauto>h1 classheading-element dirauto>itzap-ebeans/h1>a iduser-content-itzap-ebeans classanchor aria-labelPermalink: itzap-ebeans href#itzap-ebeans>svg classocticon octicon-link viewBox0 0 16 16 version1.1 width16 height16 aria-hiddentrue>path dm7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z>/path>/svg>/a>/div>p dirauto>strong>itzap-ebeans/strong> provides an easy to use library for building reactive DAO with flexible schema models.Visit my a hrefhttp://itzap.com/sql-database-with-flexible-schema/ relnofollow>ITZap blog/a> to read more about this project./p>div classmarkdown-heading dirauto>h3 classheading-element dirauto>How To Build/h3>a iduser-content-how-to-build classanchor aria-labelPermalink: How To Build href#how-to-build>svg classocticon octicon-link viewBox0 0 16 16 version1.1 width16 height16 aria-hiddentrue>path dm7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z>/path>/svg>/a>/div>ul dirauto>li>Clone the following projects:ul dirauto>li>code>git clone git@github.com:avinokurov/itzap-parent.git/code>/li>li>code>git clone git@github.com:avinokurov/itzap-common.git/code>/li>li>code>git clone git@github.com:avinokurov/itzap-rxjava.git/code>/li>li>code>git clone git@github.com:avinokurov/itzap-ebeans.git/code>/li>/ul>/li>li>Build all projectsul dirauto>li>code>cd itzap-parent && mvn clean install/code>/li>li>code>cd ../itzap-common && mvn clean install/code>/li>li>code>cd ../itzap-rxjava && mvn clean install/code>/li>li>code>cd ../itzap-ebeans && mvn clean install/code>/li>/ul>/li>li>Exampleul dirauto>li>code>itzap-beans/code> project contains sample a hrefhttps://github.com/avinokurov/itzap-ebeans/blob/master/src/test/java/com/itzap/ebeans/test/dao/UserDao.java>UserDao/a> implementation/li>/ul>/li>/ul>/article>/div>h3>Code/h3>p>Complete implementation can be found here:/p>div classmarkdown-github> div classmarkdown-github-labels> label classgithub-link> a hrefhttps://github.com/avinokurov/itzap-ebeans target_blank>Check it out on github/a> label classgithub-last-update> Last updated: 12/12/2019 20:14:47/label> /label> /div> /div> /div> /article> article classpost-191 post type-post status-publish format-standard hentry category-bug-of-the-day category-code category-docker category-executable-jar category-java category-maven tag-api tag-download tag-nexus tag-rest tag-sonatype itemscope itemtypehttp://schema.org/Article> header classpost-info> h1> a hrefhttps://itzap.com/sonatype-nexus-rest-api-search-download/> sonatype nexus Rest API search download /a> /h1> time classpost-time datetime2019-10-22 itempropdatePublished> October 22, 2019 /time> /header> div classpost-content itemproparticleBody> h3>Scenario/h3>p>Let’s say you built strong>spring-boot/strong> executable jar and uploaded it into strong>nexus/strong> repository. To deploy your spring-boot application you create a strong>Dockerfile/strong> that downloads your jar using strong>nexus/strong> rest strong>search/strong> and strong>download/strong> API. For example:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"dockerfile","mime":"text/x-dockerfile","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Dockerfile","modeName":"docker"}>FROM openjdk:8-jre-alpineMAINTAINER itzap <mailer@itzap.com>WORKDIR /RUN wget -O app-service.jar \ https://nexus.companyUrl.com/nexus/service/rest/v1/search/assets/download?groupcom.mycompany.service&nameapp-service&repositorycompany-snapshots&sortversion&directiondesEXPOSE 8080ENTRYPOINT "java", "-jar","app-service.jar"/pre>/div>p>When you run docker container you see the following error message:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"shell","mime":"text/x-sh","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Shell","modeName":"shell"}>no main manifest attribute, in app-service.jar/pre>/div>h2>Diagnostic/h2>p>When you build and run jar locally everything is working fine. app-service.jar inside docker container appears to be corrupted. To diagnose the issue run the code>wget/code> command from the terminal:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"shell","mime":"text/x-sh","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Shell","modeName":"shell"}>wget -O app-service.jar \ https://nexus.companyUrl.com/nexus/service/rest/v1/search/assets/download?groupcom.mycompany.service&nameapp-service&repositorycompany-snapshots&sortversion&directiondes/pre>/div>p>Notice the following results on the command line:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"shell","mime":"text/x-sh","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Shell","modeName":"shell"}>$ wget -O app-service.jar https://nexus.companyUrl.com/nexus/service/rest/v1/search/assets/download?groupcom.mycompany.service&nameapp-service&repositorycompany-snapshots&sortversion&directiondesc--2019-10-21 21:48:27-- https://nexus.companyUrl.com/nexus/service/rest/v1/search/assets/download?groupcom.mycompany.service&nameapp-service&repositorycompany-snapshots&sortversion&directiondescРаспознаётся nexus.compnyUrl.com (nexus.companyUrl.com)… 00.00.00.00Подключение к nexus.compnyUrl.com (nexus.compnyUrl.com)|00.00.00.00|:443... соединение установлено.HTTP-запрос отправлен. Ожидание ответа… 302 FoundАдрес: https://nexus.compnyUrl.com/nexus/repository/company-snapshots/com/mycompany/service/app-service/0.0.1-SNAPSHOT/app-service-0.0.1-20191021.220127-1-javadoc.jar переход--2019-10-21 21:48:28-- https://nexus.compnyUrl.com/nexus/repository/app-snapshots/com/mycompany/service/app-service/0.0.1-SNAPSHOT/app-service-0.0.1-20191021.220127-1-javadoc.jarПовторное использование соединения с nexus.compnyUrl.com:443.HTTP-запрос отправлен. Ожидание ответа… 200 OKДлина: 247463 (242K) application/java-archiveСохранение в: «app-service.jar»/pre>/div>p>Do not get all these messages in Russian fool you. This is not a Russian hacker attack. Pay attention to what is actually being downloaded. code>app-service-0.0.1-20191021.220127-1-javadoc.jar/code> code>strong>javadoc/strong>/code>!!!/p>h3>Solution/h3>p>Solution to this issue can be found in a relnoreferrer noopener aria-label (opens in a new tab) hrefhttps://help.sonatype.com/repomanager3/rest-and-integration-api/search-api target_blank>sonatype Search API/a>. Looking through documentation I came across this query parameter code>maven.classifier/code> This issue happens when your repository contains strong>javadoc/strong> jar alnog side your artifact. code> &sortversion&directiondesc/code> parameters are also critical to insure you are downloading the latest version, but not enough to uniquely identify artifact. Final URL that works looks like this:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"shell","mime":"text/x-sh","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Shell","modeName":"shell"}>https://nexus.companyUrl.com/nexus/service/rest/v1/search/assets/download?groupcom.mycompany.service&nameapp-service&repositorycompany-snapshots&sortversion&directiondesc&maven.classifier/pre>/div> /div> /article> article classpost-183 post type-post status-publish format-standard hentry category-bug-of-the-day category-class-loader category-java category-maven category-spring-boot tag-autoconfig tag-maven tag-meta-data tag-spring-boot itemscope itemtypehttp://schema.org/Article> header classpost-info> h1> a hrefhttps://itzap.com/unable-to-read-meta-data-for-class-spring-autoconfig/> Unable to read meta-data for class. Spring autoconfig /a> /h1> time classpost-time datetime2019-10-18 itempropdatePublished> October 18, 2019 /time> /header> div classpost-content itemproparticleBody> h3>Scenario/h3>p>Let’s say you are building a strong>spring-boot /strong>library and would like to tap into strong>spring-boot/strong> auto-configuration feature. You create code>class MyAutoConfiguration/code> and annotate it with the spring code>@Configuration/code> annotation. Then, in you application, you use this library as a dependency, run the application and get the following exception/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"shell","mime":"text/x-sh","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Shell","modeName":"shell"}>Caused by: java.lang.IllegalStateException: Unable to read meta-data for class com.mylib.autoconfigure.MyAutoConfiguration at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.getAnnotationMetadata (AutoConfigurationSorter.java:233) at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.getOrder (AutoConfigurationSorter.java:204) at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.access$000 (AutoConfigurationSorter.java:150) at org.springframework.boot.autoconfigure.AutoConfigurationSorter.lambda$getInPriorityOrder$0 (AutoConfigurationSorter.java:63)/pre>/div>h3>Steps to Reproduce/h3>p>Create strong>spring-boot/strong> project and add the following class/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"clike","mime":"text/x-java","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Java","modeName":"java"}>@Configurationpublic class MyAutoConfiguration { private static final Logger LOGGER LoggerFactory.getLogger(MyAutoConfiguration.class); @PostConstruct public void printConfigurationMessage() { LOGGER.info("Configuration for My Lib is complete..."); }}/pre>/div>p>Do not forget to add code>spring.factories/code> file to code>resources -> META-INF -> spring.factories/code> img loadinglazy width402 height136 classwp-image-185 stylewidth: 250px; srchttp://itzap.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-18-at-12.47.34-PM.png alt srcsethttp://itzap.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-18-at-12.47.34-PM.png 402w, http://itzap.com/wp-content/uploads/2019/10/Screen-Shot-2019-10-18-at-12.47.34-PM-300x101.png 300w sizes(max-width: 402px) 100vw, 402px />/p>p>strong>spring.factories /strong>file looks like this:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"pug","mime":"text/x-pug","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Pug","modeName":"pug"}>org.springframework.boot.autoconfigure.EnableAutoConfigurationcom.mylib.autoconfigure.MyAutoConfiguration/pre>/div>p>maven file for this project may look something like this:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"xml","mime":"application/xml","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"XML","modeName":"xml"}><parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath /> <!-- lookup parent from repository --></parent><!-- Spring --><dependencies> ...</dependencies><build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins></build>/pre>/div>p>Finally, you add your library as a dependency to your application, run it and get the runtime error mentioned above./p>h3>Diagnostic/h3>p>Online search suggests that either strong>spring.factories /strong>file is missing, or the name of the class is not correct, … Everything is checked out and fine. To make sure code>MyAutoConfiguration/code> class is in fact included I start looking into my library jar:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"shell","mime":"text/x-sh","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Shell","modeName":"shell"}>jar tvf target/mylib.jar | grep MyAutoConfiguration/pre>/div>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"shell","mime":"text/x-sh","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Shell","modeName":"shell"}>BOOT-INF/classes/com/mylib/autoconfigure/MyAutoConfiguration.class/pre>/div>p>Here, I can see that the class is under code>BOOT-INF/classes/code> root. /p>h3>Solution/h3>p>Apparently, auto configuration classes cannot be found under code>BOOT-INF/classes/code> root. The main issue with my setup was the fact that I used code>spring-boot-maven-plugin/code> to build the library module. After removing the plugin and rebuilding the library code>jar tvf target/mylib.jar | grep MyAutoConfiguration/code> is showing this:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"shell","mime":"text/x-sh","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Shell","modeName":"shell"}>com/mylib/autoconfigure/MyAutoConfiguration.class/pre>/div>p>Now, strong>spring-boot /strong>application builds fine and code>MyAutoConfiguration/code> class is found and ready to be used to configure library./p>p> /p> /div> /article> article classpost-170 post type-post status-publish format-standard hentry category-bug-of-the-day category-class-loader category-elasticsearch category-java category-maven category-spring-boot category-spring-cloud tag-elasticsearch tag-inetsockettransportaddress tag-maven tag-spring-boot itemscope itemtypehttp://schema.org/Article> header classpost-info> h1> a hrefhttps://itzap.com/java-lang-noclassdeffounderror-org-elasticsearch-common-transport-inetsockettransportaddress/> java.lang.NoClassDefFoundError: org/elasticsearch/common/transport/InetSocketTransportAddress /a> /h1> time classpost-time datetime2019-10-17 itempropdatePublished> October 17, 2019 /time> /header> div classpost-content itemproparticleBody> h3>Scenario/h3>p>In a strong>spring-boot /strong>application that uses strong>spring-boot-dependencies/strong> instead of strong>spring-boot-starter-parent/strong> and a third party library that depends on strong>elasticsearch/strong> version that is not comparable with version 6.x, elasticsearch dependency version get mixed up creating class loading issue. /p>h3>Steps to reproduce/h3>p>Create a strong>spring-boot /strong>project and include strong>spring-boot-dependencies/strong> in the dependency management section of the maven pom.xml/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"xml","mime":"text/xml","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"XML","modeName":"xml"}><properties> <spring.boot.version>2.1.6.RELEASE</spring.boot.version> <spring.cloud.version>Greenwich.RELEASE</spring.cloud.version></properties><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring.cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement>/pre>/div>p>Later, in the dependencies section include a third party library that depends on elastic search version strong>5.6.8/strong>/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"xml","mime":"text/xml","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"XML","modeName":"xml"}><dependnecies> <dependency> <groupId>com.netflix.conductor</groupId> <artifactId>conductor-es5-persistence</artifactId> <version>2.8.1</version> </dependency></dependnecies>/pre>/div>p>Note that strong>conductor-es5-persistence/strong> depends on elasticsearch version strong>5.6.8/strong>/p>p>The try to run code>mvn dependency:tree/code> on your project and observe the following: /p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"brainfuck","mime":"text/x-brainfuck","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":""}>INFO +- com.netflix.conductor:conductor-es5-persistence:jar:2.8.1:compileINFO | +- org.elasticsearch:elasticsearch:jar:6.4.3:compileINFO | | +- org.elasticsearch:elasticsearch-core:jar:6.4.3:compile/pre>/div>p>Where strong>6.4.3/strong> is coming from? /p>h3>Diagnostic/h3>p>Turns out code>mvn dependency:tree/code> shows the issue, but it does not say where code>org.elasticsearch:elasticsearch:jar:6.4.3:compile /code> is comming from. The best command for the job is:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"shell","mime":"application/x-sh","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Shell","modeName":"shell"}>mvn -Dverbosetrue help:effective-pom/pre>/div>p>This command outputs effective POM that can be redirected to a file code>mvn -Dverbosetrue help:effective-pom > ~/pom.xml/code> and analysed. The effective pom will look something like this/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"xml","mime":"application/xml","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"XML","modeName":"xml"}>...<dependency> <groupId>org.elasticsearch</groupId> <!-- org.springframework.boot:spring-boot-dependencies:2.1.6.RELEASE, line 1965 --> <artifactId>elasticsearch</artifactId> <!-- org.springframework.boot:spring-boot-dependencies:2.1.6.RELEASE, line 1966 --> <version>6.4.3</version> <!-- org.springframework.boot:spring-boot-dependencies:2.1.6.RELEASE, line 1967 --></dependency>.../pre>/div>p>Magic! now we can see exactly where the problem is:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"xml","mime":"application/xml","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"XML","modeName":"xml"}><!-- org.springframework.boot:spring-boot-dependencies:2.1.6.RELEASE, line 1967 -->/pre>/div>h2>Solution/h2>p>Lets look at this import dependency:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"xml","mime":"application/xml","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"XML","modeName":"xml"}><dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency>/pre>/div>p>strong>spring-boot-dependencies/strong> is imported, so there is no easy way to exclude elasticsearch dependency that it pulls into our project. A simple maven code><exclude>/code> will not work here. The only way to solve the issue is to bring elasticsearch dependencies into your project dependency management block like this:/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror data-setting{"mode":"xml","mime":"application/xml","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"XML","modeName":"xml"}><properties> <spring.boot.version>2.1.6.RELEASE</spring.boot.version> <spring.cloud.version>Greenwich.RELEASE</spring.cloud.version> <elasticsearch.version>5.6.8</elasticsearch.version></properties><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring.cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Elasticsearch --> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>${elasticsearch.version}</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>${elasticsearch.version}</version> </dependency> <dependency> <groupId>org.elasticsearch.distribution.integ-test-zip</groupId> <artifactId>elasticsearch</artifactId> <version>${elasticsearch.version}</version> <type>zip</type> </dependency> <dependency> <groupId>org.elasticsearch.plugin</groupId> <artifactId>transport-netty4-client</artifactId> <version>${elasticsearch.version}</version> </dependency> </dependencies></dependencyManagement>/pre>/div>p>Now run code>mvn -Dverbosetrue help:effective-pom/code> and confirm that the problem is fixed./p>p> /p> /div> /article> article classpost-153 post type-post status-publish format-standard hentry category-code category-elasticsearch category-java category-pattern category-rxjava itemscope itemtypehttp://schema.org/Article> header classpost-info> h1> a hrefhttps://itzap.com/itzap-elasticsearch-embedded-7-3/> itzap-elasticsearch client library /a> /h1> time classpost-time datetime2019-10-10 itempropdatePublished> October 10, 2019 /time> /header> div classpost-content itemproparticleBody> h3>Vision Statement/h3>p>Build 7.3.x elasticsearch embedded server into strong>g classgr_ gr_3 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace id3 data-gr-id3>itzap/g>–g classgr_ gr_5 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling id5 data-gr-id5>elasticsearch/g>/strong> library to enable easy prototyping and unit/integration testing/p>h3>How It Works/h3>p>Elasticsearch embedded server starts a single g classgr_ gr_13 gr-alert gr_gramm gr_inline_cards gr_run_anim Style multiReplace id13 data-gr-id13>g classgr_ gr_367 gr-alert gr_spell gr_inline_cards gr_disable_anim_appear ContextualSpelling ins-del multiReplace id367 data-gr-id367>elasticsearch/g> /g>code>code>Node/code>/code>g classgr_ gr_13 gr-alert gr_gramm gr_inline_cards gr_disable_anim_appear Style multiReplace id13 data-gr-id13>./g> Elasticsearch server node will be listening for incoming requests on port code>code>9200/code>/code> Elasticsearch client can be configured to access g classgr_ gr_102 gr-alert gr_gramm gr_inline_cards gr_disable_anim_appear Grammar only-ins replaceWithoutSep id102 data-gr-id102>embedded/g> server using the following g classgr_ gr_101 gr-alert gr_spell gr_inline_cards gr_disable_anim_appear ContextualSpelling ins-del multiReplace id101 data-gr-id101>url/g>: code>http://localhost:9200/code> Elasticsearch embedded server will create data and home temp folders that will be deleted g classgr_ gr_177 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace id177 data-gr-id177>opon/g> application close./p>h3>Code/h3>p>Here is the main class that implements elasticsearch embedded server node/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"clike","mime":"text/x-java","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Java","modeName":"java"}>public class EmbeddedElasticSearchServer implements IOData { private static final Logger LOGGER LoggerFactory.getLogger(EmbeddedElasticSearchServer.class); private Node instance; private int port; private final AnyConfig config; public EmbeddedElasticSearchServer(AnyConfig config) { this.config config; } private static class PluginConfigurableNode extends Node { PluginConfigurableNode(Settings input, Map<String, String> properties, Path configPath, Supplier<String> defaultNodeName, Collection<Class<? extends Plugin>> classpathPlugins) { super(InternalSettingsPreparer.prepareEnvironment(input, properties, configPath, defaultNodeName), classpathPlugins, false); } } @Override public synchronized Completable start() { return new RunnableCommand<Void>("cmd-start") { @Override protected Void run() { Settings settings getSettings(); instance new PluginConfigurableNode(settings, ImmutableMap.of(), null, () -> config.getString(EsConfig.CLUSTER_NAME), singletonList(Netty4Plugin.class)); try { instance.start(); Runtime.getRuntime().addShutdownHook(new Thread(() -> { try { if (instance ! null) { instance.close(); } } catch (IOException e) { LOGGER.error("Error closing ElasticSearch"); } })); LOGGER.info("ElasticSearch cluster {} started in local mode on port {}", instance.settings().get("cluster.name"), port); return null; } catch (NodeValidationException e) { throw new IZapException("Failed to start embedded elastic search server", e); } } }.toCompletable(); } @Override public synchronized Completable stop() { return new RunnableCommand<Void>("cmd-stop") { @Override protected Void run() { if (instance ! null && !instance.isClosed()) { LOGGER.info("Stopping Elastic Search"); try { instance.close(); instance null; LOGGER.info("Elastic Search on port {} stopped", port); } catch (IOException e) { throw new IZapException("Failed to close elastic search embedded server", e); } } return null; } }.toCompletable(); } private Settings getSettings() { String clusterName config.getString(EsConfig.CLUSTER_NAME); String host config.getString(EsConfig.HOST); port config.getInt(EsConfig.PORT); try { File dataDir Files.createTempDirectory(clusterName + "_" + System.currentTimeMillis() + "data").toFile(); FileUtils.forceDeleteOnExit(dataDir); cleanDataDir(dataDir.getAbsolutePath()); File homeDir Files.createTempDirectory(clusterName + "_" + System.currentTimeMillis() + "-home").toFile(); cleanDataDir(homeDir.getAbsolutePath()); FileUtils.forceDeleteOnExit(homeDir); Settings.Builder settingsBuilder Settings.builder() .put("cluster.name", clusterName) .put("http.host", host) .put("http.port", port) .put("transport.tcp.port", port + 100) .put(EsConfig.DATA_PATH.getName(), dataDir.getAbsolutePath()) .put(EsConfig.HOME_PATH.getName(), homeDir.getAbsolutePath()) .put("http.cors.enabled", true) .put("node.data", true) .put("http.type", "netty4") .put("transport.type", "netty4"); return settingsBuilder.build(); } catch (IOException e) { throw new IZapException("Failed to create temp data/home dir.", e); } }}/pre>/div>p>Elasticsearch embedded server implementation is using a relnoreferrer noopener aria-labelRunnableCommand (opens in a new tab) hrefhttp://itzap.com/itzap-rxjava-reactive-programming/ target_blank>g classgr_ gr_5 gr-alert gr_gramm gr_inline_cards gr_disable_anim_appear Grammar only-ins replaceWithoutSep id5 data-gr-id5>RunnableCommand/g>/a> command pattern to g classgr_ gr_6 gr-alert gr_gramm gr_inline_cards gr_disable_anim_appear Style multiReplace id6 data-gr-id6>implement /g>code>code>start/code>/code>g classgr_ gr_6 gr-alert gr_gramm gr_inline_cards gr_disable_anim_appear Style multiReplace id6 data-gr-id6> and/g> code>code>stop/code>/code>methods. Please note that a relnoreferrer noopener hrefhttp://itzap.com/itzap-rxjava-reactive-programming/ target_blank>RunnableCommand/a> returns Completable and not Observable. g classgr_ gr_14 gr-alert gr_gramm gr_inline_cards gr_run_anim Style multiReplace id14 data-gr-id14>Sice /g>code>code>a relnoreferrer noopener aria-label (opens in a new tab) hrefhttps://github.com/ReactiveX/RxJava/wiki/What%27s-different-in-2.0#nulls target_blank>Observable<Void>/a>/code>/code>g classgr_ gr_14 gr-alert gr_gramm gr_inline_cards gr_disable_anim_appear Style multiReplace id14 data-gr-id14> is/g> no longer permitted in a relnoreferrer noopener aria-labelRxJava2 (opens in a new tab) hrefhttps://github.com/ReactiveX/RxJava/wiki/What%27s-different-in-2.0 target_blank>RxJava2/a> and code>code>start/code>/code>/code>code>stop/code>/code> methods have no return values. Here is the unit test for the g classgr_ gr_166 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace id166 data-gr-id166>elasticsearch/g> embedded server/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"clike","mime":"text/x-java","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"Java","modeName":"java"}>public class EmbeddedElasticSearchServerTest { private EmbeddedElasticSearchServer server; @Before public void setup() { AnyConfig config ConfigBuilder.builder(ConfigType.TYPE_SAFE) .setFileName(this.getClass() .getResource("/es-config.properties").getFile()) .build(); server new EmbeddedElasticSearchServer(config); } @Test public void startTest() { server.start().blockingGet(); server.stop().blockingGet(); }}/pre>/div>p>Elasticsearch dependencies/p>div classwp-block-codemirror-blocks-code-block code-block>pre classCodeMirror cm-s-idea data-setting{"mode":"xml","mime":"application/xml","theme":"idea","lineNumbers":false,"styleActiveLine":false,"lineWrapping":false,"readOnly":true,"language":"XML","modeName":"xml"}><dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.3.1</version></dependency><dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.3.1</version></dependency><dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>7.3.1</version></dependency>/pre>/div> /div> /article> nav classposts-navigation> div classposts-navigation-left> a hrefhttps://itzap.com/page/2/ >Older Posts/a> /div> div classposts-navigation-right> /div> /nav>/div> nav classsidebar> div idsearch-4 classwidget widget_search>form methodget classsearch-form actionhttps://itzap.com/ rolesearch> input typetext classsearch-text names value placeholderSearch … /> input typesubmit classsearch-submit namesubmit idsearchsubmit valueSearch />/form>/div>div idtext-3 classwidget widget_text> div classtextwidget>p>a hrefhttps://ts.la/aleksey28668 target_blank relnoopener>My Tesla Referral Linkimg loadinglazy classalignnone wp-image-257 srchttp://itzap.com/wp-content/uploads/2020/01/model3-300x169.png alt width254 height143 srcsethttp://itzap.com/wp-content/uploads/2020/01/model3-300x169.png 300w, http://itzap.com/wp-content/uploads/2020/01/model3-1024x575.png 1024w, http://itzap.com/wp-content/uploads/2020/01/model3-768x431.png 768w, http://itzap.com/wp-content/uploads/2020/01/model3-700x393.png 700w, http://itzap.com/wp-content/uploads/2020/01/model3.png 1440w sizes(max-width: 254px) 100vw, 254px />/a>a hrefhttps://www.youracclaim.com/badges/46772921-625d-4a91-952b-6d1e13972fda target_blank relnoopener>img loadinglazy classalignnone srchttps://images.youracclaim.com/size/680x680/images/68468004-5a85-4f3b-bc58-590773979486/AWS-CloudPractitioner-2020.png alt width179 height179 />/a>a hrefhttps://www.youracclaim.com/badges/46772921-625d-4a91-952b-6d1e13972fda>AWS Certified Cloud Ractitioner/a>/p>/div> /div> div idrecent-posts-3 classwidget widget_recent_entries> h2 classwidget-title>Resent Posts/h2> ul> li> a hrefhttps://itzap.com/how-to-access-http-request-body-object-using-spring-handlermethodargumentresolver/>How to access HTTP request body object using spring HandlerMethodArgumentResolver/a> span classpost-date>March 3, 2020/span> /li> li> a hrefhttps://itzap.com/zuul-useseparatethreadpools-and-rejectedexecutionexception/>Zuul useSeparateThreadPools and RejectedExecutionException/a> span classpost-date>January 22, 2020/span> /li> li> a hrefhttps://itzap.com/factory-method-textencryptor-threw-exception/>Factory method ‘textEncryptor’ threw exception/a> span classpost-date>December 7, 2019/span> /li> li> a hrefhttps://itzap.com/swagger-ui-in-jersey-api/>Swagger UI in Jersey Application/a> span classpost-date>December 5, 2019/span> /li> li> a hrefhttps://itzap.com/java-builder-pattern-with-shared-state/>Builder Pattern with Shared State/a> span classpost-date>November 9, 2019/span> /li> /ul> /div>div idcategories-4 classwidget widget_categories>h2 classwidget-title>Categories/h2> ul> li classcat-item cat-item-17>a hrefhttps://itzap.com/category/code/bug-of-the-day/>Bug of the day/a>/li> li classcat-item cat-item-7>a hrefhttps://itzap.com/category/code/java/class-loader/>Class Loader/a>/li> li classcat-item cat-item-1>a hrefhttps://itzap.com/category/code/ titlethe blog post about coding technique>code/a>/li> li classcat-item cat-item-8>a hrefhttps://itzap.com/category/docker/>Docker/a>/li> li classcat-item cat-item-33>a hrefhttps://itzap.com/category/code/java/ebean/>ebean/a>/li> li classcat-item cat-item-16>a hrefhttps://itzap.com/category/elasticsearch/>elasticsearch/a>/li> li classcat-item cat-item-14>a hrefhttps://itzap.com/category/micro-service/embedded-tomcat/>embedded Tomcat/a>/li> li classcat-item cat-item-15>a hrefhttps://itzap.com/category/maven/executable-jar/>executable jar/a>/li> li classcat-item cat-item-11>a hrefhttps://itzap.com/category/frameworks/>frameworks/a>/li> li classcat-item cat-item-13>a hrefhttps://itzap.com/category/frameworks/hk2/>hk2/a>/li> li classcat-item cat-item-4>a hrefhttps://itzap.com/category/code/java/>Java/a>/li> li classcat-item cat-item-12>a hrefhttps://itzap.com/category/frameworks/jersey/>Jersey/a>/li> li classcat-item cat-item-9>a hrefhttps://itzap.com/category/maven/>maven/a>/li> li classcat-item cat-item-10>a hrefhttps://itzap.com/category/micro-service/>micro-service/a>/li> li classcat-item cat-item-5>a hrefhttps://itzap.com/category/code/pattern/>Pattern/a>/li> li classcat-item cat-item-6>a hrefhttps://itzap.com/category/code/rxjava/>RxJava/a>/li> li classcat-item cat-item-51>a hrefhttps://itzap.com/category/frameworks/spring/>spring/a>/li> li classcat-item cat-item-18>a hrefhttps://itzap.com/category/frameworks/spring-boot/>spring-boot/a>/li> li classcat-item cat-item-50>a hrefhttps://itzap.com/category/frameworks/spring-cloud/>spring-cloud/a>/li> li classcat-item cat-item-32>a hrefhttps://itzap.com/category/code/sql/>sql/a>/li> li classcat-item cat-item-43>a hrefhttps://itzap.com/category/swagger/>swagger/a>/li> li classcat-item cat-item-49>a hrefhttps://itzap.com/category/frameworks/zuul/>zuul/a>/li> /ul> /div>div idwpcw_social-4 classwidget wpcw-widgets wpcw-widget-social>ul>li classhas-label>a hrefhttps://github.com/avinokurov target_blank titleVisit ITZap Development on GitHub>span classfa fa-2x fa-github>/span>GitHub/a>/li>li classhas-label>a hrefhttps://www.instagram.com/aleksy.vinokurov target_blank titleVisit ITZap Development on Instagram>span classfa fa-2x fa-instagram>/span>Instagram/a>/li>li classhas-label>a hrefhttps://www.linkedin.com/in/avinokurovpub target_blank titleVisit ITZap Development on LinkedIn>span classfa fa-2x fa-linkedin>/span>LinkedIn/a>/li>li classhas-label>a hrefhttps://twitter.com/a_vinokurov00 target_blank titleVisit ITZap Development on Twitter>span classfa fa-2x fa-twitter>/span>Twitter/a>/li>/ul>/div> /nav>footer idfooter> a hrefhttps://espressoprogrammer.com/espresso-programmer-wp-theme relauthor titleEspresso Programmer>Espresso Programmer/a> empowered by a hrefhttps://wordpress.org/ relexternal titleWordPress is open source software you can use to create a beautiful website, blog, or app.>WordPress/a>/footer>!-- main content div -->script typetext/javascript srchttps://itzap.com/wp-content/plugins/coblocks/dist/js/coblocks-animation.js?ver2.12.1 idcoblocks-animation-js>/script>script typetext/javascript srchttps://itzap.com/wp-content/plugins/custom-scrollbar/asset/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js?ver5.7.14 idmalihu-custom-scrollbar-js>/script>script typetext/javascript idcustom_scrollbar_enabler-js-extra>/* !CDATA */var customScrollbarEnabler {scrollbars:{name:code-block,status:true,selector:.long_code,height:{size:400,unit:px},width:{size:,unit:px},position:inside,inline_css:{property:,value:},theme:light,mouseWheel:{enable:true,scrollAmount:auto},keyboard:{enable:true,scrollAmount:auto},scrollButtons:{enable:false,scrollAmount:auto,scrollType:stepless},mCSB_draggerContainer:,mCSB_dragger:,mCSB_dragger_bar:,mCSB_draggerRail:,mCSB_scrollTools:,initialize_on_ajax_load:false,responsive:{enable:false,screen_width_range:1,0}},debugMode:0,pluginName:Custom Scrollbar 1.3.6};/* > *//script>script typetext/javascript srchttps://itzap.com/wp-content/plugins/custom-scrollbar/asset/js/custom-scrollbar-enabler.min.js?ver5.7.14 idcustom_scrollbar_enabler-js>/script>script typetext/javascript srchttps://itzap.com/wp-includes/js/wp-embed.min.js?ver5.7.14 idwp-embed-js>/script>/div>!-- #page -->/body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]