{"id":20477287,"url":"https://github.com/jpomykala/spring-higher-order-components","last_synced_at":"2026-01-11T17:40:58.615Z","repository":{"id":50112640,"uuid":"153264733","full_name":"jpomykala/spring-higher-order-components","owner":"jpomykala","description":"⚡️ Preconfigured components to speedup Spring Boot development","archived":false,"fork":false,"pushed_at":"2024-05-17T10:51:36.000Z","size":194,"stargazers_count":101,"open_issues_count":0,"forks_count":20,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-06T10:12:51.225Z","etag":null,"topics":["aws-s3","aws-ses","boilerplate","higher-order-component","java","logging","spring","spring-boot","spring-boot-starter"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jpomykala.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-16T10:09:10.000Z","updated_at":"2025-03-03T19:29:32.000Z","dependencies_parsed_at":"2024-05-17T11:55:23.714Z","dependency_job_id":null,"html_url":"https://github.com/jpomykala/spring-higher-order-components","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpomykala%2Fspring-higher-order-components","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpomykala%2Fspring-higher-order-components/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpomykala%2Fspring-higher-order-components/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpomykala%2Fspring-higher-order-components/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jpomykala","download_url":"https://codeload.github.com/jpomykala/spring-higher-order-components/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248717251,"owners_count":21150388,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws-s3","aws-ses","boilerplate","higher-order-component","java","logging","spring","spring-boot","spring-boot-starter"],"created_at":"2024-11-15T15:27:16.784Z","updated_at":"2026-01-11T17:40:58.572Z","avatar_url":"https://github.com/jpomykala.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"![spring-hoc](https://i.imgur.com/8LA1Xcp.png)\n\n[![Build Status](https://travis-ci.org/jpomykala/spring-higher-order-components.svg?branch=master)](https://travis-ci.org/jpomykala/spring-higher-order-components)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.jpomykala/spring-higher-order-components/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.jpomykala/spring-higher-order-components)\n[![codecov](https://codecov.io/gh/jpomykala/spring-higher-order-components/branch/master/graph/badge.svg)](https://codecov.io/gh/jpomykala/spring-higher-order-components)\n[![Maintainability](https://api.codeclimate.com/v1/badges/4fc54f7f19a610dc5d42/maintainability)](https://codeclimate.com/github/jpomykala/spring-higher-order-components/maintainability)\n\nBoilerplate components for Spring Boot. \n- [x] [E-mail sending with step builder](#enableemailsending-annotation)\n- [x] [Request logging](#enablerequestlogging-annotation)\n- [x] [Files uploading to Amazon S3](#enablefileuploading-annotation)\n- [x] [Response wrapping](#enableresponsewrapping-annotation) (works with Swagger / SpringFox!)\n- [x] [Easy to use CORS filter](#enablecors-annotation)\n\n## Installation\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.jpomykala\u003c/groupId\u003e\n  \u003cartifactId\u003espring-higher-order-components\u003c/artifactId\u003e\n  \u003cversion\u003e1.0.11\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n[Check version in maven repository](https://mvnrepository.com/artifact/com.jpomykala/spring-higher-order-components)\n\n## Motivation\n\n- Write inline code\n- Duplicate code a few times in different spots\n- Extract duplicate code into methods\n- Use your abstractions for a while\n- See how that code interacts with other code\n- Extract common functionality into internal library\n- Use internal library for extended periods of time\n- Really understand how all of the pieces come together\n- Create external open source library (we are here now)\n\nsource: [https://nickjanetakis.com](https://nickjanetakis.com/blog/microservices-are-something-you-grow-into-not-begin-with)\n\n*** \n\n## `@EnableEmailSending` annotation\n\nThis component gives you simple API to send emails using Amazon SES service. Spring HOC will automatically create for you Amazon SES component if bean doesn't exist.\n\n### Configuration\n\n- Provide **verified** sender email address ``spring-hoc.mail.sender-email-address``\n- Provide AWS credentials ``spring-hoc.aws.access-key``, ``spring-hoc.aws.secret-key``, ``spring-hoc.aws.region``\n\n#### Example `application.yml` configuration for e-mail sending\n\n```yml\nspring-hoc:\n  aws:\n    access-key: xxxxxxxx\n    secret-key: xxxxxxxx\n    region: eu-west-1\n  mail:\n    sender-email-address: \"no-reply@mydomain.com\"    \n```\nThis properties are **required**.\n\n#### Tip\nYou can put `My Company Name \u003cno-reply@mydomain.com\u003e` in `sender-email-address` property to show \"My Company Name\" in e-mail apps instead plain e-mail.\nReference: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-concepts-email-format.html\n\n### How to send e-mail?\n\nUse ``EmailRequest`` step builder to create request.\n\n```java\nEmailRequest.builder()\n            .to(\"jpomykala@example.com\")\n            .subject(\"Hey, I just met you and this is crazy\")\n            .body(\"But here's my number, so call me maybe\")\n            .build();\n```\n\nNow it's time to send email. You have 2 options here.\n- ``@Autowire MailService`` and invoke ``sendEmail(EmailRequest)``.\n- Publish ``EmailRequest`` using ``ApplicationEventPublisher``\n\nThat's all!\n\n### Example application with sending email (SES)\n\n```java\n@SpringBootApplication\n@EnableEmailSending\npublic class MySpringBootApplication {\n\n  public static void main(String[] args) {\n    SpringApplication.run(MySpringBootApplication.class, args);\n  }\n\n  // Send e-mail by event publishing, Spring HOC will listen to EmailRequest objects \n  @Autowired\n  private ApplicationEventPublisher eventPublisher;\n\n  @GetMapping(\"/send-email-by-event-publishing\")\n  public void sendEmailByEventPublishing(){\n    EmailRequest emailRequest = EmailRequest.builder()\n            .to(\"jakub.pomykala@gmail.com\")\n            .subject(\"Hey, I just met you and this is crazy [event publishing]\")\n            .body(\"But here's my number, so call me maybe\")\n            .build();\n\n    eventPublisher.publishEvent(emailRequest);\n  }\n  \n  // Send e-mail by mail service provided by Spring HOC and @EnableEmailSending annotation\n  @Autowired\n  private MailService mailService;\n\n  @GetMapping(\"/send-email-by-mail-service\")\n  public void sendEmailByMailService(){\n    EmailRequest emailRequest = EmailRequest.builder()\n            .to(\"jakub.pomykala@gmail.com\")\n            .subject(\"Hey, I just met you and this is crazy [mail service]\")\n            .body(\"But here's my number, so call me maybe\")\n            .build();\n\n    mailService.send(emailRequest);\n  }\n}\n```\n\n*** \n\n## `@EnableRequestLogging` annotation\n\nAdds logging requests, populate MDC with:\n- user (IP address by default)\n- requestId (UUID by default).\n\n### Example application with request logging\n\n```java\n@SpringBootApplication\n@EnableRequestLogging\npublic class MySpringBootApplication {\n\n  public static void main(String[] args) {\n    SpringApplication.run(MySpringBootApplication.class, args);\n  }\n\n  @Autowired\n  private MyUserService userService;\n\n  // [OPTIONAL] customize configuration\n  @Bean\n  public LoggingFilter loggingFilter(LoggingFilterFactory loggingFilterFactory) {\n    return loggingFilterFactory\n            .withPrincipalProvider(new PrincipalProvider() {\n              @Override\n              public String getPrincipal(HttpServletRequest request) {\n                return userService.findUserName(request);\n              }\n            })\n            .createFilter();\n  }\n}\n\n```\n\n\n### Customization of request logging\n```java\n@Bean\npublic LoggingFilter loggingFilter(LoggingFilterFactory loggingFilterFactory){\n  return loggingFilterFactory\n          .withPrincipalProvider() // [optional] PrincipalProvider implementation \n          .withRequestIdProvider() // [optional] RequestIdProvider implementation\n          .withCustomMdc(\"user\", \"[u:%s][rid:%s]\") // [optional] MDC key, String.format()\n          .createFilter();\n}\n```\n\n*** \n\n## `@EnableFileUploading` annotation\n\nThis annotation autoconfigures Amazon S3 component if bean doesn't exit.\n\n``@Autowire UploadService`` gives you ability to upload files using overloaded methods:\n- ``void upload(@NotNull UploadRequest uploadRequest)``\n- ``void upload(@NotNull MultipartFile file)``\n- ``void upload(@NotNull MultipartFile file, @NotNull String path)``\n- ``void upload(byte[] bytes, String fileKey)``\n- ``void upload(byte[] bytes, String fileKey, ObjectMetadata metadata)``\n- ``String upload(byte[] bytes)`` // path is autogenerated (sha256 hash)\n\n### Example ``application.yml`` configuration for file uploading\n\n```\nspring-hoc:\n  aws:\n    access-key: xxxxxxxx\n    secret-key: xxxxxxxx\n    region: eu-west-1\n  s3:\n    bucket-name: my-bucket\n```\nThis properties are **required.***\n\n### Example application with files uploading\n\n```java\n@SpringBootApplication\n@EnableFileUploading\npublic class MySpringBootApplication {\n\n  public static void main(String[] args) {\n    SpringApplication.run(MySpringBootApplication.class, args);\n  }\n\n  @Autowired\n  private UploadService uploadService;\n\n  @GetMapping(\"/upload-file\")\n  public String uploadFile(@RequestBody MultipartFile multipartFile) throws IOException {\n    String s3DownloadUrl = uploadService.upload(multipartFile);\n    return s3DownloadUrl;\n  }\n}\n```\n\n*** \n\n## `@EnableResponseWrapping` annotation\n\nEvery `@RestController` output will be wrapped into `RestResponse\u003cT\u003e` object for JSON it will look like as follows:\n\n```\n{\n  msg: \"OK\"\n  status: 200\n  data: \u003cyour data\u003e\n  pageDetails: \u003cpage details if you return Page from controller\u003e\n}\n```\n\n`RestResponse` static contructors:\n  \n  - `RestResponse ok(Object body)`\n  - `RestResponse ok(Object body, PageDetails pageDetails)`\n  - `RestResponse empty(String message, HttpStatus status)`\n  - `RestResponse of(String message, HttpStatus status, Object data)`\n  - `RestResponse of(String message, HttpStatus status, Object data, PageDetails pageDetails)`\n  \nEvery output will be wrapped into `RestResponse` [see this issue](https://github.com/jpomykala/spring-higher-order-components/issues/4)\n\nResponse wrapping can be disabled for specific endpoinds by using `@DisableWrapping` annotation on method.\n\n### Example application with response wrapping\n\n```java\n@SpringBootApplication\n@EnableResponseWrapping\npublic class MySpringBootApplication {\n\n  public static void main(String[] args) {\n    SpringApplication.run(MySpringBootApplication.class, args);\n  }\n\n  @GetMapping(\"/wrap-pojo\")\n  public MyPojo wrapResponse() {\n    MySpringBootApplication.MyPojo myPojo = new MyPojo(\"Jakub\", \"Pomykala\");\n    return myPojo;\n  }\n  \n  @Autowired\n  private MyPojoRepository myPojoRepository;\n\n  @GetMapping(\"/wrap-pojo-page\")\n  public Page\u003cMyPojo\u003e wrapPageResponse() {\n    Page\u003cMyPojo\u003e myPojos = myPojoRepository.findAll();\n    return myPojos;\n  }\n  \n  public class MyPojo {\n    private String firstName;\n    private String lastName;\n    // getters and setters\n  }\n}\n```\n\n*** \n\n## `@EnableCORS` annotation\n\nThis annotation adds filter which handles CORS requests.\n\n### Example `application.yml` configuration for CORS\n\n```yml\nspring-hoc:\n  cors:\n    allow-credentials: true\n    allowed-origins:\n      - \"https://my-frontend-application.com\"\n      - \"https://jpomykala.com\"\n    allowed-methods:\n      - GET\n      - POST\n      - PATCH\n      - DELETE\n```\nThis properties are **optional.**\n\nBy default CORS will accept all origins, all HTTP methods and all popular headers.\n\n### Example application with CORS filter\n\n```java\n@SpringBootApplication\n@EnableCORS\npublic class MySpringBootApplication {\n\n  public static void main(String[] args) {\n    SpringApplication.run(MySpringBootApplication.class, args);\n  }\n\n}\n```\n\n\n# Contribution\n\nWould you like to add something or improve source? Create new issue, let's discuss it \n\n- **If in doubt, please discuss your ideas first before providing a pull request. This often helps avoid a lot of unnecessary work. In particular, we might prefer not to prioritise a particular feature for another while.**\n- Fork the repository.\n- The commit message should reference the issue number.\n- Check out and work on your own fork.\n- Try to make your commits as atomic as possible. Related changes to three files should be committed in one commit.\n- Try not to modify anything unrelated.\n\nSource: https://github.com/jOOQ/jOOQ\n\n# More\n\n- Check out my [website](https://jpomykala.com)\n\n# License\nGNU General Public License v3.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpomykala%2Fspring-higher-order-components","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjpomykala%2Fspring-higher-order-components","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpomykala%2Fspring-higher-order-components/lists"}