{"id":1901,"date":"2025-11-20T10:00:02","date_gmt":"2025-11-20T15:00:02","guid":{"rendered":"http:\/\/www.mymiller.name\/wordpress\/?p=1901"},"modified":"2025-11-20T10:00:02","modified_gmt":"2025-11-20T15:00:02","slug":"http-server-jar","status":"publish","type":"post","link":"https:\/\/www.mymiller.name\/wordpress\/java_http\/http-server-jar\/","title":{"rendered":"HTTP Server in your Jar"},"content":{"rendered":"\n<p>I recently had the need to be able to access a couple of files from a number of computers and didn&#8217;t want to setup network shares and things. &nbsp;These were a simple text files, that I was logging information into. However I was going to be moving around a number of systems and needed to be able to check on those logs occasionally. &nbsp;Obviously I didn&#8217;t want to install a full blown web-server for a couple of hours of work, to access those files. &nbsp;Why not create my own HTTP server? &nbsp;Well it&#8217;s much easier than it used to be, which even then it was amazingly easy, but in today&#8217;s java world it&#8217;s even easier. &nbsp;In fact I got carried away a little bit on it, and made it a bit fancier than it needed to be.<\/p>\n\n\n\n<p><span style=\"color: #ff0000;\"><strong>WARNING<\/strong>: This is NOT a robust, secure HTTP Server, this is a simple HTTP Server, for when you need one, without the hassle of installing one. &nbsp;If you need robust, and secure, then go install Apache HTTP, Apache Tomcat or something else!<\/span><\/p>\n\n\n\n<p>First step you need to use com.sun.net.httpserver.HttpServer. &nbsp;The main step you need is to create a couple of methods:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>main() to use to start from the command line easily and to be able to restart if necessary.<\/li><li>start() to use to setup the properties for the HttpServer.<\/li><\/ul>\n\n\n\n<p>Next you&#8217;ll want to create a ThreadPoolExecutor to handle the incoming requests. &nbsp;That&#8217;s basically it. &nbsp;I have included the entire file below along with the properties files for configuration. &nbsp;I trust that you can follow along!<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package name.mymiller.httpserver;\n\nimport java.io.IOException;\nimport java.net.InetSocketAddress;\nimport java.util.List;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.logging.Level;\n\nimport com.sun.net.httpserver.HttpServer;\nimport name.mymiller.extensions.job.AbstractService;\nimport name.mymiller.extensions.job.JobManager;\nimport name.mymiller.extensions.lang.reflect.ReflectionUtil;\nimport name.mymiller.extensions.lang.singleton.SingletonInterface;\nimport name.mymiller.extensions.log.LogManager;\nimport name.mymiller.httpserver.handlers.ContextHandlerInterface;\nimport name.mymiller.httpserver.handlers.HttpHandlerAnnotation;\n\nimport javax.management.ReflectionException;\n\n\n\/**\n * @author jmiller HTTP System to start an HTTP Server and load handlers\n *\/\n@SuppressWarnings(\"restriction\")\npublic class HttpSystem extends AbstractService implements SingletonInterface&lt;HttpSystem>\n{\n\t\/**\n\t * Configuration Node\n\t *\/\n\tprivate static final String\tHTTP\t\t\t= \"\/http\";\n\t\/**\n\t * Thread Pool size for handling requests\n\t *\/\n\tprivate static int\t\t\tPOOL_SIZE\t\t= 10;\n\t\/**\n\t * Max Thread Pool size\n\t *\/\n\tprivate static int\t\t\tMAX_POOL_SIZE\t= 25;\n\t\/**\n\t * Thread Keep Alive Time\n\t *\/\n\tprivate static int\t\t\tKEEP_ALIVE_TIME\t= 30;\n\n\t\/**\n\t * Global Instance for the HTTP System\n\t *\/\n\tprivate static HttpSystem globalInstance = null;\n\n\t\/**\n\t * Port to list on\n\t *\/\n\tprivate static int\t\t\tLISTEN_PORT = 8080;\n\n\t\/**\n\t * Backlog for HTTP System\n\t *\/\n\tprivate static int\t\t\tBACK_LOG = 10;\n\n\t\/**\n\t *\n\t * @return Global Instance of the HTTPS System\n\t *\/\n\tpublic static HttpSystem getInstance()\n\t{\n\t\tif (HttpSystem.globalInstance == null)\n\t\t{\n\t\t\tHttpSystem.globalInstance = new HttpSystem();\n\t\t}\n\t\treturn HttpSystem.globalInstance;\n\t}\n\n\tpublic static int getMaxPoolSize() {\n\t\treturn MAX_POOL_SIZE;\n\t}\n\n\tpublic static void setMaxPoolSize(int maxPoolSize) {\n\t\tMAX_POOL_SIZE = maxPoolSize;\n\t}\n\n\tpublic static int getListenPort() {\n\t\treturn LISTEN_PORT;\n\t}\n\n\tpublic static void setListenPort(int listenPort) {\n\t\tLISTEN_PORT = listenPort;\n\t}\n\n\tpublic static int getBackLog() {\n\t\treturn BACK_LOG;\n\t}\n\n\tpublic static void setBackLog(int backLog) {\n\t\tBACK_LOG = backLog;\n\t}\n\n\t\/**\n\t * HTTP Server reference\n\t *\/\n\tprivate HttpServer\t\t\t\t\t\thttpServer\t= null;\n\t\/**\n\t * Queue to hold incoming requests\n\t *\/\n\tprivate ArrayBlockingQueue&lt;Runnable>\tqueue\t\t= null;\n\t\/**\n\t * Thread Pool Executor for the HTTP Serever\n\t *\/\n\tprivate ThreadPoolExecutor\t\t\t\tthreadPool\t= null;\n\n\t\/**\n\t * Instantiates a new simple http server.\n\t *\/\n\tprivate HttpSystem()\n\t{\n\t}\n\n\t\/**\n\t * @return Active Thread Count\n\t *\/\n\tpublic int getActiveCount()\n\t{\n\t\treturn this.threadPool.getActiveCount();\n\t}\n\n\t\/**\n\t *\n\t * @return InetSocketAddress of the HTTP Server\n\t *\/\n\tpublic InetSocketAddress getAddress()\n\t{\n\t\treturn this.httpServer.getAddress();\n\t}\n\n\t\/**\n\t *\n\t * @return Count of Completed Tasks by the Thread Pool\n\t *\/\n\tpublic long getCompletedTaskCount()\n\t{\n\t\treturn this.threadPool.getCompletedTaskCount();\n\t}\n\n\t\/**\n\t *\n\t * @return Maximum size of the Thread Pool has reached\n\t *\/\n\tpublic int getLargestPoolSize()\n\t{\n\t\treturn this.threadPool.getLargestPoolSize();\n\t}\n\n\t\/**\n\t *\n\t * @return Maximum size the thread pool can reach\n\t *\/\n\tpublic int getMaximumPoolSize()\n\t{\n\t\treturn this.threadPool.getMaximumPoolSize();\n\t}\n\n\t\/**\n\t *\n\t * @return Current size of the thread pool\n\t *\/\n\tpublic int getPoolSize()\n\t{\n\t\treturn this.threadPool.getPoolSize();\n\t}\n\n\t\/**\n\t *\n\t * @return Current Task Count for the Thread Pool\n\t *\/\n\tpublic long getTaskCount()\n\t{\n\t\treturn this.threadPool.getTaskCount();\n\t}\n\n\t@Override\n\tprotected void service()\n\t{\n\t\tfinal HttpSystem system = HttpSystem.getInstance();\n\n\t\tsynchronized (system)\n\t\t{\n\t\t\twhile (!system.isShutdown())\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tsystem.wait(1000);\n\t\t\t\t} catch (final InterruptedException e)\n\t\t\t\t{\n\t\t\t\t\tLogManager.getLogger(HttpSystem.class).info(\"Http System Thread Interupted:\" + e.getMessage());\n\t\t\t\t}\n\t\t\t\tif (system.isRestart())\n\t\t\t\t{\n\t\t\t\t\tLogManager.getLogger().info(\"Restarting HTTP Server System\");\n\t\t\t\t\tsystem.stop(HttpConstants.DELAY_TIME);\n\t\t\t\t\tsystem.start();\n\t\t\t\t\tsystem.setRestart(false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t\/**\n\t * Start.\n\t *\/\n\t@Override\n\tpublic void start()\n\t{\n\t\tthis.start(null);\n\t}\n\n\t\/**\n\t * Start method accpeing handlers to use for this HTTP Server.\n\t * @param handlers\n\t *\/\n\tpublic void start(ContextHandlerInterface&#91;] handlers)\n\t{\n\t\ttry\n\t\t{\n\t\t\tLogManager.getLogger().info(\"Starting HTTP Server System\");\n\n\t\t\tif (this.threadPool != null)\n\t\t\t{\n\t\t\t\tthis.threadPool.shutdown();\n\t\t\t}\n\t\t\tif (this.queue != null)\n\t\t\t{\n\t\t\t\tthis.queue.clear();\n\t\t\t}\n\t\t\t\/\/ Create a default executor\n\t\t\tthis.queue = new ArrayBlockingQueue&lt;>(HttpSystem.MAX_POOL_SIZE);\n\t\t\tthis.threadPool = new ThreadPoolExecutor(HttpSystem.POOL_SIZE, HttpSystem.MAX_POOL_SIZE,\n\t\t\t\t\tHttpSystem.KEEP_ALIVE_TIME, TimeUnit.SECONDS, this.queue);\n\n\t\t\t\/\/ Create HttpServer which is listening on the given port\n\t\t\tthis.httpServer = HttpServer.create(\n\t\t\t\t\tnew InetSocketAddress(HttpSystem.getListenPort()),HttpSystem.getBackLog());\n\t\t\tthis.httpServer.setExecutor(this.threadPool);\n\n\t\t\tfor (final ContextHandlerInterface handler : handlers)\n\t\t\t{\n\t\t\t\tLogManager.getLogger(HttpSystem.class)\n\t\t\t\t\t\t.info(\"Loading Handler: \" + handler.getClass().getCanonicalName());\n\n\t\t\t\tfinal String context = handler.getClass().getAnnotation(HttpHandlerAnnotation.class).context();\n\t\t\t\tLogManager.getLogger(HttpSystem.class).info(\"Adding Handler: \" + handler + \" Context: \" + context);\n\n\t\t\t\tthis.httpServer.createContext(context, handler);\n\t\t\t}\n\t\t\tLogManager.getLogger(HttpSystem.class)\n\t\t\t\t\t.info(\"Server is started and listening on port \" + this.httpServer.getAddress().getPort());\n\t\t\tthis.httpServer.start();\n\n\t\t\tJobManager.getInstance().createService(\"HTTP System\", HttpSystem.getInstance());\n\t\t} catch (final IOException e)\n\t\t{\n\t\t\tLogManager.getLogger(this.getClass()).log(Level.SEVERE, \"IOException Error in starting HTTPSystem\", e);\n\t\t} catch (final SecurityException e)\n\t\t{\n\t\t\tLogManager.getLogger(this.getClass()).log(Level.SEVERE, \"SecurityException\", e);\n\t\t} catch (final IllegalArgumentException e)\n\t\t{\n\t\t\tLogManager.getLogger(this.getClass()).log(Level.SEVERE, \"IllegalArgumentException\", e);\n\t\t}\n\t}\n\n\t\/**\n\t * Force a stop of the server\n\t *\n\t * @param delay\n\t *            the maximum time in seconds to wait until exchanges have\n\t *            finished.\n\t *\/\n\t@Override\n\tprotected void stop(final int delay)\n\t{\n\t\tthis.httpServer.stop(delay);\n\t\tLogManager.getLogger(HttpSystem.class).info(\"Server is stopped.\");\n\t}\n}\n<\/code><\/pre>\n\n\n\n<p>Next thing is you need some handlers, and one of my next posts will discuss those!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently had the need to be able to access a couple of files from a number of computers and didn&#8217;t want to setup network shares and things. &nbsp;These were a simple text files, that I was logging information into. However I was going to be moving around a number of systems and needed to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1902,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[459],"tags":[69],"series":[226],"class_list":["post-1901","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java_http","tag-java-2","series-http-server-in-a-jar"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2016\/09\/http-875180_640.jpg?fit=640%2C452&ssl=1","jetpack-related-posts":[{"id":1906,"url":"https:\/\/www.mymiller.name\/wordpress\/java_http\/http-server-command-handler-in-a-jar\/","url_meta":{"origin":1901,"position":0},"title":"HTTP Server Command Handler in a Jar","author":"Jeffery Miller","date":"November 24, 2025","format":false,"excerpt":"Today, I'm going to share with you a command handler for the HTTP Server I presented previously. \u00a0This is a handler to extend the abilities of that HTTP Server in a Jar to provide you the ability to stop, restart and get status of it, if needed. WARNING: This is\u2026","rel":"","context":"In &quot;Java HTTP&quot;","block_context":{"text":"Java HTTP","link":"https:\/\/www.mymiller.name\/wordpress\/category\/java_http\/"},"img":{"alt_text":"filters","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2016\/09\/http-875180_640.jpg?fit=640%2C452&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2016\/09\/http-875180_640.jpg?fit=640%2C452&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2016\/09\/http-875180_640.jpg?fit=640%2C452&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3747,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_config\/secure-your-secrets-encrypting-values-with-spring-cloud-config\/","url_meta":{"origin":1901,"position":1},"title":"Secure Your Secrets: Encrypting Values with Spring Cloud Config","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"In the world of microservices, Spring Cloud Config provides a centralized way to manage externalized configurations for your applications. But what about sensitive data like database passwords or API keys? That\u2019s where encryption comes in. This blog post will guide you through the process of encrypting your sensitive values using\u2026","rel":"","context":"In &quot;Spring Config&quot;","block_context":{"text":"Spring Config","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_config\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/security-5726869_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/security-5726869_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/security-5726869_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/security-5726869_1280-jpg.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/security-5726869_1280-jpg.avif 3x"},"classes":[]},{"id":3671,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_ai\/spring-cloud-data-flow-orchestrating-machine-learning-pipelines\/","url_meta":{"origin":1901,"position":2},"title":"Spring Cloud Data Flow: Orchestrating Machine Learning Pipelines","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"In the dynamic world of machine learning, the journey from raw data to a deployed model involves a series of intricate steps. Spring Cloud Data Flow (SCDF) emerges as a powerful ally, offering a comprehensive platform to streamline and manage these complex data pipelines. In this guide, we\u2019ll delve into\u2026","rel":"","context":"In &quot;Spring AI&quot;","block_context":{"text":"Spring AI","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_ai\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/ai-generated-8411275_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/ai-generated-8411275_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/ai-generated-8411275_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/ai-generated-8411275_1280-jpg.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/ai-generated-8411275_1280-jpg.avif 3x"},"classes":[]},{"id":3641,"url":"https:\/\/www.mymiller.name\/wordpress\/spng_security\/integrating-java-spring-with-keycloak-a-comprehensive-guide\/","url_meta":{"origin":1901,"position":3},"title":"Integrating Java Spring with Keycloak: A Comprehensive Guide","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Java Spring, a popular framework for building enterprise-level applications, can seamlessly integrate with Keycloak, a robust open-source Identity and Access Management (IAM) solution. This combination offers a powerful way to implement secure authentication, authorization, and user management features in your Spring-based applications. Let\u2019s explore how to achieve this integration along\u2026","rel":"","context":"In &quot;Spring Security&quot;","block_context":{"text":"Spring Security","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spng_security\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/08\/ghost-7571881_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/08\/ghost-7571881_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/08\/ghost-7571881_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/08\/ghost-7571881_1280-jpg.avif 2x"},"classes":[]},{"id":3744,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_config\/3744\/","url_meta":{"origin":1901,"position":4},"title":"Spring Cloud Config: Choosing the Right Backend Storage","author":"Jeffery Miller","date":"December 23, 2025","format":false,"excerpt":"Spring Cloud Config offers a flexible way to manage your application\u2019s configuration. A crucial step is selecting the right backend to store your configuration data. Let\u2019s explore popular options, their pros and cons, configuration details, and the necessary dependencies for Maven and Gradle. 1. Git Pros: Version Control: Leverage Git\u2019s\u2026","rel":"","context":"In &quot;Spring Config&quot;","block_context":{"text":"Spring Config","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_config\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/04\/woman-8696271_640.jpg?fit=438%2C640&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":3903,"url":"https:\/\/www.mymiller.name\/wordpress\/docker\/the-s3-local-dev-trick-using-minio-to-simplify-cloud-native-developmen\/","url_meta":{"origin":1901,"position":5},"title":"The S3 Local Dev Trick: Using MinIO to Simplify Cloud-Native Developmen","author":"Jeffery Miller","date":"August 25, 2025","format":false,"excerpt":"As a software architect building cloud-native solutions, you know that working with cloud services like AWS S3 can be a bit tricky in a local development environment. You don't want to constantly connect to a remote bucket, and setting up complex local testing environments can be a pain. But what\u2026","rel":"","context":"In &quot;Docker&quot;","block_context":{"text":"Docker","link":"https:\/\/www.mymiller.name\/wordpress\/category\/docker\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/08\/ai-generated-9268117_1280.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/08\/ai-generated-9268117_1280.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/08\/ai-generated-9268117_1280.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/08\/ai-generated-9268117_1280.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/08\/ai-generated-9268117_1280.avif 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/1901","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/comments?post=1901"}],"version-history":[{"count":8,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/1901\/revisions"}],"predecessor-version":[{"id":2916,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/1901\/revisions\/2916"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media\/1902"}],"wp:attachment":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media?parent=1901"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/categories?post=1901"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/tags?post=1901"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/series?post=1901"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}