DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

How does AI transform chaos engineering from an experiment into a critical capability? Learn how to effectively operationalize the chaos.

Data quality isn't just a technical issue: It impacts an organization's compliance, operational efficiency, and customer satisfaction.

Are you a front-end or full-stack developer frustrated by front-end distractions? Learn to move forward with tooling and clear boundaries.

Developer Experience: Demand to support engineering teams has risen, and there is a shift from traditional DevOps to workflow improvements.

The Latest Frameworks Topics

article thumbnail
How To Become a Symfony Certified Engineer: Your Path to Expertise in the Software Industry
This article will guide you to become a Symfony Certified Engineer, from understanding the framework’s core principles to practical experience and exam preparation.
October 25, 2023
by Alireza Rahmani Khalili DZone Core CORE
· 3,441 Views · 5 Likes
article thumbnail
How to Create Your Own 'Dynamic' Bean Definitions in Spring
Written by Benjamin Steinert (@ben_steinert), Lean Java Expert @comsysto Recently, I joined a software project with a Spring/Hibernate-based software stack, which is shipped in an SAAS-like manner, but the databases of the customers need to be separated from each other. Sounds easy for you? Ok let’s see what we have in detail. 1. Baseline study Requirement: There is a software product that can be sold to different customers, but the provider wants to keep the sensible data of the customer in separate data sources. Every customer/login has only access to exactly one data source. In a, let’s say, ‘simple’ Spring setup, one would simply add all databases to the configuration type of his choice. Spring currently offers four different ways of container configuration: XML-based (old-fashion) Annotation-based (almost old-fashion) Code-based (pretty awesome) Property-file-based (exotic, haven’t heard of it yet, right? We will come to that later again) If you are interested in the details about the different possibilities, I refer to the Spring Reference Manual. Customers get a pile of logins which are associated to a specific customer key, which should delegate to the correct database. There is always only one database relevant per customer. Quick as a shot, the experienced Spring developer will refer to the ‘AbstractRoutingDataSource‘ which stores a Map of data sources internally. Based on your implementation of determineCurrentLookupKey() – typically a ThreadLocal value is accessed – the correct data source from the internal map is chosen for opening a connection. The Spring Security experts will quickly show you how to introduce the customer key to your current session which you can easily access in your AbstractRoutingDataSource. It looks even more powerful in combination with Jndi, because it provides a look-up mechanism to search for JndiResources based on names. All that sounds nice apparently. But this approach has two drawbacks for us: One routing DataSource will consequently mean, one Hibernate SessionFactory, which is not acceptable in the context of Hibernate 2nd level cache usage. Read more on this right here: http://forum.spring.io/forum/spring-projects/data/25399-swapping-datasource-for-hibernate-what-happens-with-the-2nd-level-cache The Jndi lookup strategy hides the actual data sources and does not expose them to the Spring context. But sometimes it is good to have them for example if you think of database migration approaches like Flyway for example. For now, lets forget about these problems. We want to use the AbstractRoutingDataSource but without Jndi lookup functionality and don’t care about Hibernate performance ;). 2. The first solution in action Initially, when the application was rolled out for the first time, there was only one customer present. Apart from that, a demo customer was created to prove the multiple-customer feature. No one was really complaining about the fact that a developer needs to insert the data source configuration for every new customer. Everything looked good, until the day came, where a second customer was contracted. First of all we should set up a test environment, with a separate data source. Then the real one. Temporarily we thought about having a fifth ‘customer’ for running various integration tests. The team finally recognized, that the task of setting up the data source beans should be pushed to OPS somehow, because they already have to define the correct JndiResource in the servlet context. 3. Where only few seem to have gone before New developer-driven requirement: Setting up a new customer is an OPS task, hence, introducing a new data source should not affect the development team, because there is nothing to develop! A first brainstorming session brought up only one obvious idea: We need to partly expose our Spring XML config. “With great power comes great responsibility” and to be honest, no one really wants to share the power of configuring a Spring container. After a short recherche session, we found many questions dealing with the same sort of topic: “How to dynamically create spring beans based on some sort of configuration provided without rebuilding the war file?” http://stackoverflow.com/questions/3853498/multi-user-datasources-spring-hibernate http://stackoverflow.com/questions/860918/hibernate-spring-using-multiple-datasources Our approach with the ‘AbstractRoutingDataSource’ was referenced sometimes which confirmed our initial approach. But those especially arose my attention: http://stackoverflow.com/questions/10804885/dynamic-spring-bean-creation?rq=1 http://stackoverflow.com/questions/15328904/dynamically-declare-beans-at-runtime-in-spring http://stackoverflow.com/questions/21221125/spring-context-dynamic-change http://www.carlobonamico.com/blog/?p=55 My idea was to have our very own Spring Bean definition approach which does not affect the war file! I immediately started to search for bean definition alternatives and also stumbled upon the Spring JdbcBeanDefinitionReader and the above mentionedPropertiesBeanDefinitionReader. Both classes helped me understanding how Spring internally collects all the different bean definition details before initializing the beans. (A good resource for understanding, how a Spring ApplicationContext gets initialized is this SpringONE presentation.) I got temporarily discouraged, as I saw, that I can’t simply add a BeanDefinitionReader implementation somewhere, to an ApplicationContext. It felt wrong to implement my own ApplicationContext so I had one last chance. The fourth link provides an approach how to programatically create bean definitions with a BeanFactoryPostProcessor (BFPP) implementation. When you first read the javadoc it sounds a bit like the wrong way, even the bean name itself does not really imply to create bean definitions. Second thing is, that BFPP implementations assume, that all bean definitions are already in place, so the order of execution would become essential. But we are lucky, “there is some Spring for it” of course ;). In Spring 3.0.1 an interface extension to BFPP was introduced, the BeanDefinitionRegistryPostProcessor (BDRPP) (I love these names :)). Manu Cornet – Bonkers World Blog 4. The solution I decided to go for it and confined myself for a prototyping weekend. This is the list of acceptance criteria I defined: Based on the following line of configuration, the application should initialize following certain rules: customerKeys=customer_x, customer_y, demo_customer, ui_test The customer keys are identical to the set of possible keys provided by the login mechanism. A user can only have one customerKey assigned. A single data source is created per customerKey and will be managed by the AbstractRoutingDataSource. There were many pitfalls an dead-ends coming around this weekend. That’s why I prefer to show you the solution and explain why I did it like that. 4.1) How to get the ‘customerKey’ property injected in a BeanDefinitionRegistryPostProcessor? Well not the common way. Because BeanDefinitionRegistryPostProcessors are instantiated in a very early stage of the initialization process, you can’t use functionality like @Autowired or@Value. The technical reason can be looked up in the SpringONE presentation. Now the only things you can do: Access a SystemProperty / ServletContextParam *juck* Add the Spring Environment to your BeanDefinitionRegistryPostProcessor A short explanation, why the Spring Environment is helpful here: Since 3.1 Spring separates the configuration from the ApplicationContext, which means, that stuff like defined config properties and activated spring profiles got their own interfaces. So it is good practice to initialize your Environment before a single bean is instantiated or even defined. There are many conventions, which setup your environment automatically, but the true power comes along if you do it on your own. But that’s a topic for a new post. For the impatient here are some good resources to get a first impression: http://spring.io/blog/2011/02/11/spring-framework-3-1-m1-released/ http://blog.jamesdbloom.com/UsingPropertySourceAndEnvironment.html 4.2) Core implementation Now, this is what our BeanDefinitionRegistryPostProcessor now looks like: public class DataSourcesBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor { private final List customerKeys; public DataSourcesBeanFactoryPostProcessor(Environment springEnvironment) { parseCustomerKeys(springEnvironment.getProperty("customerKeys")); } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { for (String customerKey : customerKeys) { String dataSourceName = "dataSource_" + customerKey; BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(JndiObjectFactoryBean.class); definitionBuilder.addPropertyValue("jndiName", "jdbc/" + dataSourceName); registry.registerBeanDefinition(dataSourceName, definitionBuilder.getBeanDefinition()); } } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // we actually only add new beans, but do not post process the existing definitions } private static List parseCustomerKeys(String rawCustomerKeys) { if (StringUtils.isEmpty(rawCustomerKeys)){ throw new IllegalArgumentException("Property 'customerKeys' is undefined."); } return Collections.unmodifiableList(Arrays.asList(StringUtils.split(rawCustomerKeys, ","))); } } 4.3) Get it running! Now Spring offers again different possibilities how to actually add a custom BeanFactoryPostProcessor / BeanDefinitionRegistryPostProcessor to the set of processors executed: @Component would be possible for beans implementing BeanFactoryPostProcessor in general, but we need the Spring Environment inside to access the customerKeys. And in that early stage, no Autowiring takes place. Create an XML BeanConfig entry for it. (Oldschool we don’t want to maintain XML files any longer ;) ) JavaConfig not possible, because the AnnotationScanners for it are BeanDefinitionRegistryPostProcessors itself: See SPR-7868. Add the BDRPP programmatically to the ApplicationContext during initialization: public class MyApplicationContextInitializer implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext applicationContext) { ConfigurableEnvironment springEnvironment = applicationContext.getEnvironment(); applicationContext.addBeanFactoryPostProcessor(new DataSourcesBeanFactoryPostProcessor(springEnvironment)); } } In the likely case of developing a web application, please don’t forget to define the initializer in you web.xml: contextInitializerClasses your.package.MyApplicationContextInitializer If you are lucky and OPS offers you a Servlet 3.0+ environment, the programmatic approach should be self-explanatory. Looks useful? Thanks :). 4.4) Plugging it together. The last thing missing is the initialization of the AbstractRoutingDataSource. And there it gets a bit bumpy. What we now have, is a set of factory beans which do a jndi lookup for adding those DataSources to our context. Later we want to bunde all those beans into the routing datasource, but then, we wont be able to know which datasource belongs to which customer. Although the customerKey is part of the bean name and the jndi path by convention, both are not rechable when injecting by the DataSource interface. Hmmm. Well we can rely on our bean name creation strategy once I think. Based on that, this is our JavaConfig for creating the AbstractRoutingDataSource: @Configuration public class RepositoryConfig { private String[] customerKeys; @Autowired private ApplicationContext applicationContext; @Value("${customerKeys}") public void setCustomerKeys(String rawCustomerKeys){ // parseCustomerKeys() extracted to Util class this.customerKeys = Util.parseCustomerKeys(rawCustomerKeys); } @Bean public AbstractRoutingDataSource routingDataSource(){ AbstractRoutingDataSource routingDataSource = new CustomerRoutingDataSource(); Map customerIndexMap = createCustomerMap(); routingDataSource.setTargetDataSources(customerIndexMap); return routingDataSource; } private Map createCustomerMap() { HashMap result = new HashMap(); for (String customerKey : customerKeys) { // could also be extracted to Util class to centralize contract String beanName = "dataSource_" + customerKey; DataSource dataSource = lookupBean(beanName, DataSource.class); result.put(customerKey, dataSource); } return result; } private T lookupBean(String beanName, Class clazz) { T bean = applicationContext.getBean(beanName, clazz); if (bean == null) { throw new MyStartupException("Mandatory Spring bean '" + beanName + "' missing! Aborting"); } return bean; } } The presented solution can generally be used for dynamically defining a set of beans of the same type which should take part in the whole Spring bean life cycle. 5.) Conclusion, drawbacks and upcomings With reaching 1600 words, I will take a break. But I won’t leave without summarizing the open topics so far: Why do we want to use Flyway for that. The current solution lacks the possibility to use Hibernate 2nd level caching. Will there be a solution? How can I efficiently use the Spring Environment for doing some config magic? Is there a possibility to inject or create whole maps of beans which would provide access to the beanName and probably be directly injected into the AbstractRoutingDataSource? I hope there will be time to discuss it :) So long! Have fun!
October 24, 2023
by Comsysto Gmbh
· 105,810 Views · 4 Likes
article thumbnail
That Can Not Be Tested!: Spring Cache and Retry
Learn how to write automated tests in order to ensure that given Spring features are used properly and discover generic advice on how to improve unit tests.
October 24, 2023
by Daniel Buza
· 11,730 Views · 5 Likes
article thumbnail
Popular Enterprise Architecture Frameworks
Appropriate EA framework selection is critical for Enterprise Architects based on the Organization's needs and goals.
October 24, 2023
by Ravi Kiran Mallidi DZone Core CORE
· 5,481 Views · 4 Likes
article thumbnail
How To Deploy the ELK Stack on Kubernetes
This article will explore a step-by-step guide on deploying the ELK Stack on Kubernetes. By the end of this guide, you'll have a fully functional ELK stack setup.
October 24, 2023
by Pavlo Konobeyev
· 11,601 Views · 3 Likes
article thumbnail
Data Quality Assurance: A Framework for the Data-Driven Age
Transition from a reactive to a proactive Data Quality Assurance approach. Unlock the full potential of your data assets, reduce risks, and build trust.
October 24, 2023
by Eduardo Moore
· 2,203 Views · 1 Like
article thumbnail
.NET Multi-Targeting in Harmony With Sitecore's Multi-Site Management
This approach improves code reusability, enhances compatibility, and facilitates smooth transitions between different .NET versions.
October 24, 2023
by Kapil Rawal
· 1,977 Views · 2 Likes
article thumbnail
Angular vs. Flutter for Web App Development: Know Which One Is Best?
We will compare Angular and Flutter frameworks to help you decide which one is better suited for developing your web app.
October 24, 2023
by Masudul Herry
· 4,590 Views · 2 Likes
article thumbnail
5 Must-Have Angular Grid Row Features and How To Use Them
What are the must-have Angular Grid Row features to consider when working on your next project? In this article, we talk about the top five. Find out more.
October 20, 2023
by Zdravko Kolev
· 5,758 Views · 5 Likes
article thumbnail
Packaging Libraries in iOS: A Comprehensive Guide
This article helps iOS developers create SDKs, covering library choices, dependencies, formats, and dynamic linkers for better app startup.
October 18, 2023
by Shaunak Jagtap
· 3,066 Views · 1 Like
article thumbnail
Event-Driven Architecture With Serverless Functions – Part 1
In this series of articles, we are going to explain what is the missing piece in stream processing, and in this part, we’ll start from the source.
October 14, 2023
by Yaniv Ben Hemo
· 6,527 Views · 3 Likes
article thumbnail
ReactJS for AI and Machine Learning: A Powerful Combination
In this blog post, we will explore how ReactJS and AI/ML can be combined to build powerful and interactive web applications.
October 14, 2023
by Atul Naithani
· 17,186 Views · 2 Likes
article thumbnail
Top 30+ Spring Boot Interview Questions With Answers
This post will present you with a curated set of often-requested Spring Boot interview questions to help you ace your interviews.
October 13, 2023
by Gyan Mishra
· 8,534 Views · 7 Likes
article thumbnail
How To Make Codable Work With Swift’s New Observation Framework and the @Observable Macro in SwiftUI
The tutorial guides you through the creation of a landmarks app featuring a list of landmarks and a detail page for each landmark where users can mark it as a favorite.
October 12, 2023
by Anders Forssell
· 2,352 Views · 1 Like
article thumbnail
php[tek] 2023: A Community of Communities Powering the Internet
The PHP community came together in Chicago for php[tek] 2023, sharing best practices and the latest updates about the tech that runs over 77% of the internet.
October 12, 2023
by Dwayne McDaniel
· 2,600 Views · 1 Like
article thumbnail
How To Generate Spring Properties Documentation
Are you struggling to keep the documentation of your Spring configuration properties in line with the code? Learn how to solve the issue in this article.
October 11, 2023
by Gunter Rotsaert DZone Core CORE
· 8,010 Views · 9 Likes
article thumbnail
Java 21 Is a Major Step for Java: Non-Blocking IO and Upgraded ZGC
Let's understand how Virtual Threads are a major benefit for developers and the whole Java ecosystem and how ZGC improves on Java's already solid GC capabilities.
October 11, 2023
by Theodore Ravindranath
· 19,539 Views · 19 Likes
article thumbnail
Best Practices To Deal With Javax to Jakarta Migration
In this post, I’ll explain everything you need to know to upgrade to Jakarta EE 9+ successfully and in almost no time.
October 11, 2023
by Ondro Mihalyi
· 67,867 Views · 4 Likes
article thumbnail
Flutter Live Streaming With Video SDK
Discover the power of interactive live streaming with Flutter! Learn how to create a dynamic live-streaming app using Flutter and a video SDK.
October 11, 2023
by Utpalsinh Parmar
· 2,413 Views · 1 Like
article thumbnail
Architecting Scalable ASP.NET Core Web APIs With Abstract Factory Method and Onion Architecture
Consider using Abstract Factory Method when implementing ASP.NET Core Web API with Onion Architecture. Adjustments may be needed based on data access tech.
October 10, 2023
by Sardar Mudassar Ali Khan
· 3,216 Views · 1 Like
  • Previous
  • ...
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • ...
  • Next

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: