Blog

Missional Living — Maximizing Your Ministry Part 1 (Acts 6:1-7)

Maximizing Your Ministry Part 1 (Acts 6:1-7)

Introduction

The admonition to care for the poor is found throughout the Scriptures (Exodus 23:10-11; Leviticus 23:22; Deuteronomy 15:7-11; Esther 9:22; Psalm 14:6, 41:1; Proverbs 14:21; Matthew 11:5, 19:21; Romans 15:26; Galatians 2:10; Luke 14:13, 21). Caring for the poor is one way that a person in the community of faith does business with God (Proverbs 19:17) and honors Him. How does showing kindness to the poor honor God? There are at least two reasons why kindness to the poor honors God. First, the poor are made in the image of God (Genesis 1:27; Proverbs 14:31; 22:2); showing kindness to the poor is a way of showing respect for His image (1 John 4:20). Second, rendering compassion to the poor in our fellowships is one way we demonstrate our new birth (1 John 5:1).

Figure 1 – Poor people in the Bible come in many types. Especially important to God are widows (James 1:27).

Within the segment of society regarded as poor there is a subsection that is especially dear to God’s heart: widows and orphans (Exodus 22:22-24; Deuteronomy 10:18; Psalm 68:5; Proverbs 15:25; James 1:26-27). Widows, especially in the time of the first church, were particularly vulnerable to poverty. The agencies of modern governments that care for the poor did not exist. But the early church, under its apostolic leadership, had been mindful of this group. There was a daily distribution of alms aimed at meeting the needs of widows. This distribution to the widows had worked for a while; it had been effective when the church was fairly homogenous. But with exponential growth in the fellowship came a corresponding diversity in the demographics. The church is now comprised of local Jews and those that have immigrated to Jerusalem. The local Jews speak Aramaic (or Mishnaic Hebrew). Those that have immigrated to Jerusalem are called Hellenists (Acts 6:1). Who are the Hellenists and how do they differ from the Hebrews? F.F. Bruce summarizes:

The church of Jerusalem, we are now told, comprised both “Hebrews” and “Hellenists.” The main distinction between the two groups was probably linguistic: the Hellenists were Jews whose habitual language was Greek and who attended Greek-speaking synagogues; the Hebrews spoke Aramaic (or Mishnaic Hebrew) and attended synagogues where the service was conducted in Hebrew. Many of the Hellenists had affinities with the lands of the Jewish dispersion around the Mediterranean shores, whereas the Hebrews were Palestinian Jews; there were doubtless several minor social and cultural differences between the two groups. In the Jewish world as a whole there were tensions between them, and some of these tensions endured between members of the two groups who had joined the “disciples” (Bruce, 1988, p. 120).

The Hellenists are Jews of the Diaspora that have assimilated some aspects of Greek culture – especially language. Arnold G. Fruchtenbaum, in his commentary on Acts explains that their was a grievance growing among the Hellenists against the Hebrews:

[W]hile the church was deeply concerned about taking care of the widows, there seems to have been a prejudice in favor of the locally born, Hebrew speaking widows, over the Greek speaking widows who had immigrated into the country. The latter felt neglected and overlooked in the daily distribution (Fruchtenbaum, 2005, Kindle Locations 2723-2725).

Out of the growth caused by the ministry of the word (Acts 5:42) came diversity. Out of the diversity arose discrimination and inequity. In order to deal with inequity and discrimination there would need to be an intervention by the apostles. The handling of the matter by the twelve contains principles of missional living that are sorely needed by many fellowships and individuals today. If we are willing to listen to the voice of the early church apostles, our ministries, personal and corporate, can become more efficient and more effective. The twelve tell us to concentrate on our calling, delegate duties, and then watch God work.

Questions for Personal Study

  1. Are there indicators that your ministry is operating below its potential? This could be seen in missed opportunities due to obligations outside your calling or quality that is lower than what you are capable of?
  2. Has anyone shared with you criticism concerning your ministry that could be useful in looking for places to improve?
  3. Do you desire to raise the quality of your ministry and the quantity of people reached?

References

Bruce, F. F. (1988). The Book of the Acts. Grand Rapids, MI: Wm. B. Eerdmans Publishing Co.

Fruchtenbaum, Arnold G (2005). Commentary Series: The Book of Acts. Ariel Ministries.

Notes

The women seen in the featured image of this post were at a conference in Atlanta. Immediately to my right is Yvonne. Across the table is Virgina. I was there for the company owned by my wife and I, BIF Technologies, on business with Xtreme Solutions. After our respective work we met over prayer, the Scriptures, and worship in a public setting. We endeavored to (1) be above reproach and (2) make the most of the moment. Maximizing your ministry may be as simple as using moments that seem secular for purposes sanctified.

Calculating Sprint Velocity and Efficiency

Introduction

Are you using Agile to help your organization deliver products and/or services? If the answer to that question is yes, then you are breaking the work of bringing products and services to your customers into sprints. (If you are new to Agile and you do not know what a sprint is, I recommend Schwaber’s The Scrum Guide: The Definitive Guide to Scrum: The Rules of the Game.) A sprint in Agile is a time-boxed period.

Figure 1 – A Sprint is a Time-Boxed Period for Agile Work. The figure shows time boxing outside of Agile for time at work.

That period ranges from one to four weeks. During the sprint period a specific set of work is attempted and made ready for review by a customer. The sprint is a fundamental unit in Scrum and the Agile framework.

Your sprint is a single iteration in your product development or service delivery process. What happens during a sprint? It depends on whether your organization or team produces a product or a service. Let us say, for our discussion, that your team labors to deliver a viable version of a product. (A product could be  a piece of software, alternators for a particular line of trucks, or a newsletter for a non-profit ministry). Your sprint begins with a planning meeting where the team defines the sprint goal and selects items from the product backlog to work on in the time-boxed period.

Figure 2 – Sprint tasks are selected from the backlog for completion in the time-boxed period.

Your sprint ends with a review and retrospective to assess the work completed and improve processes for the next sprint.

Getting better at sprints should be the ongoing goal of any organization that is leveraging Agile. To improve at sprinting there has to be business intelligence that tells the team how they did on the sprint. There have to be metrics and visuals that provide insight on (1) how things went down, (2) what went well, and (3) what could be done better.

  • Burndown Chart — A burndown chart in Agile is a visual tool that assists a team in tracking the progress of a project. It showings the amount of work remaining over time. The chart typically has time on the horizontal axis and work remaining (often in story points or hours) on the vertical axis.

Figure 3 – Example Sprint Burndown Chart

  • Velocity — a tool that tracks the amount of work a team completes during a sprint. This metric usually is measured in story points or hours. It helps teams understand their progress, forecast future performance, and plan upcoming sprints more effectively by analyzing trends in completed work over time.
  • Goal Success Rate — refers to the percentage of goals (or objectives) that a team successfully meets or achieves within a sprint. It measures how effectively a team delivers on its planned commitments. This metric helps to assess the team’s performance and ability to meet its targets.

Let us take on just one of these business intelligence components — velocity. Calculating velocity in Agile is important for several reasons:

  • Predictability and Planning — Velocity calculations help teams estimate how much work they can complete in future sprints based on past performance. By knowing the average velocity, teams can make more accurate sprint plans, ensuring that they commit to a realistic amount of work. Velocity also helps with release planning. Using velocity a team is equipped to predict how many sprints are needed to complete a given set of features; this helps in release planning and setting realistic deadlines.
  • Tracking Performance — By tracking velocity over multiple sprints, teams can monitor their performance. A consistent velocity (cruising) or improving velocity (acceleration) indicates a stable or improving team dynamic. Likewise, a declining velocity (deceleration) may signal overcommitment, burnout, or other inefficiencies that need to be addressed. Watching velocity for fluctuations can help in identifying bottlenecks or other emerging issues. Vigilance in this area can help a team leader to be proactive in preventing problems that will sink a project or cause serious delays.
  • Transparency — Velocity provides an easy-to-understand metric that can be shared with stakeholders to communicate the team’s progress and capacity. This transparency builds trust and helps manage stakeholder expectations regarding timelines and deliverables. With good velocity data, stakeholders and teams can make informed decisions about scope adjustments, prioritization of work, or resource allocation to ensure that the project stays on track and aligned with business goals.

Using Jira to Calculate Velocity and Efficiency

Jira is a popular project management and issue tracking software packaged developed by Atlassian. It is widely used by Agile teams to manage their software development processes. Let us say that we have a software product called XSIPBI. Further, let us say that we are working through the development and release of features using sprints. In the table below we provide basic metrics for each sprint. The velocity in each sprint is the sum of story points for completed tasks.

Sprint Committed Completed / Velocity Goal Success Rate Start Date End Date Duration Days Efficiency ( pts / day )
XSIPBI Sprint 011 20.8 3.8 18% 2024-05-22 2024-06-04 10 0.380
XSIPBI Sprint 012 27.5 22.4 81% 2024-06-04 2024-06-27 18 1.244
XSIPBI Sprint 013 28.8 16.5 57% 2024-06-27 2024-07-16 14 1.179
XSIPBI Sprint 014 60.5 45.5 75% 2024-07-16 2024-08-05 15 3.033
XSIPBI Sprint 015 4.8 12.5 260% 2024-08-05 2024-08-13 7 1.786

The formula for velocity, for those who like the notation of the Mathematics, is very simple and given in the equation below:

In this equation V is velocity and taski is the story points for the task with index i. While velocity is often touted as important, I find efficiency more informative as a metric of team performance in a sprint. Efficiency tells us the rate at which story points were being completed for each day of the sprint. The efficiency of a team is a ratio that makes it easy to compare the rate at which work was done across sprints. The sprint with the highest velocity in Table 1 is Sprint 014. More important than its velocity is the fact that it has the highest efficiency; three story points were completed every day… on average. The efficiency of Sprint 014 is higher than the efficiency of any of the other sprints in the table. Give a day to Sprint 012 and it will only finish 1.24 story points. Give the same amount of time to Sprint 014 and it will get more than twice the story points completed.

I regard sprint Efficiency like the MPG of a car. With a 2024 Ford Bronco Sasquatch (2.7L, 6-cyl, AWD) I can go 17 miles on a gallon of gas in city driving; in other words, it has a city MPG of 17. With a 2024 Ford Maverick (2.5L, 4-cyl) I can go 33 miles on a gallon of gas in city driving; it has city MPG of 33. Given a single gallon of gas, the 2024 Ford Maverick is more efficient. Of course this is an oversimplification of how car efficiency is measured. We should also consider things like towing capacity and the number of cylinders in the engine. Likewise, when measuring the efficiency of a sprint we should also take into account the number of people involved and other resources required for getting the work done.

Conclusion

If you will add velocity to your business intelligence review of a sprint you will be able to use history to do better planning. A story point commitment that is being considered should be evaluated in the light of past commitments and how much was actually completed – the velocity. Don’t commit to story points that history shows are a case of sandbagging or pipe dreaming; make realistic goals using the velocity history of your team. Also, it would be good to calculate the efficiency of each sprint. This ratio gives you the mean of story points your team completed each day. I regard this value as the true velocity and can use it to say whether or not our team can expect to finish all of the tasks before the end of the sprint. Using efficiency I am equipped to decide which task should get the attention if we know that not all of them can get done.

Side Note on Time-Boxing

Time-boxing refers to the project management practice of allocating a fixed amount of time to an activity, task, or event. Once the set time limit, or “time box,” is reached, the activity or task is stopped. What if the task or activity is not complete? It is still stopped. When time boxing of work is used to manage work, the task, activity, or event, regardless of whether it is completed, is brought to a halt. This concept is an often-used time management technique to ensure that work progresses efficiently and that time is used effectively.

Is it practical? Very! In a practical sense, time-boxing keeps teams on track by forcing them to acknowledge the scarcity of time. Teams or individuals using time boxing focus on specific tasks within a predetermined timeframe, avoiding scope creep and helping to prioritize work. For example, in a Scrum meeting, a “time-boxed” daily stand-up might be limited to 15 minutes. After 15 minutes the meeting ends. The meeting ends regardless of whether all topics have been discussed. This approach encourages concise communication and efficient use of time.

References

Schwaber, K., & Sutherland, J. (2020). The Scrum Guide: The Definitive Guide to Scrum: The Rules of the Game. Scrum.org. Retrieved from https://www.scrumguides.org/scrum-guide.html

Pressman, R. S., & Maxim, B. R. (2014). Software Engineering: A Practitioner’s Approach (8th ed.). McGraw-Hill Education.

Rubin, K. S. (2012). Essential Scrum: A Practical Guide to the Most Popular Agile Process. Addison-Wesley.

 

On Our Terms! (Acts 5:17-18, 26)

The apostles keep getting arrested. First it was just Peter and John (Acts 4:1-3). Now it is all of them (Acts 5:17-18). That is, in our passage the high priest came with a group and arrested all of the apostles. Soon after they were released by an angel (Acts 5:19-20). Today, they are being arrested again. But it is different. Notice the contrast between the arrest of yesterday (Acts 5:17-18) and today (Acts 5:26).

  • Yesterday it was a “hands-on” approach to getting the apostles. The arrest literally involved a throwing on of hands (ἐπέβαλον τὰς χεῖρας ἐπὶ τοὺς ἀποστόλους) by the captain of the temple and his officers. To understand what is meant by “laid their hands on the apostles” it helps to see that the word being translated laid (ἐπέβαλον) is found in other places (Acts 4:3; 21:27). Anyone who becomes acquainted with the other passages where ἐπέβαλον is used, can see that the arrest of the apostles was violent.
  • Today, however, the captain went with the officers and brought the apostles without violence (Acts 5:26). The apostles have most certainly reported their imprisonment, angelic visitation, and command to “speak to the people all the words of this life” (Acts 5:20). With that in mind, the captain’s attempt to arrest the apostles must be seen as evil. It is really an attempt to prevent (1) a ministry that has been helping hurting people and (2) the bringing of the message of eternal life through faith in Jesus Christ. The jealousy (indignation) of the high priest was the motivation behind the arrest. In the power of the Holy Spirit the Galileans are drawing the people away from the Sadducees to the Savior.

But, what changed? That is, why is this second attempt to get the apostles without violence. The text makes it clear: the captain and the officers are afraid.

Then the captain went with the officers and brought them without violence, for they feared the people, lest they should be stoned. (Acts 5:26)

It is obvious that the people now side with the apostles and are willing to use their greater numbers and the stones in the immediate vicinity to stop the arrest. (We must also see that the foolishness of Sadducee teachings is now on full display. Sadducees do not believe in angels (Acts 23:8). However, according to the apostles, an angel let them out of prison. Either the prison is truly dysfunctional and the apostles are lying or there is growing evidence that angels are real.) The religious leaders want to shut down an effective ministry and the people are now standing in the way. If the apostles are going to be arrested, they are going to have to be willing to go on their terms.

They are unstoppable! No weapon formed against them will prosper (Isaiah 54:17).

In His grip by His grace,
Roderick L. Barnes, Sr.

Pulling a Thread

Introduction

Some web applications require a lot of attention. If there are a lot of concurrent users, complex SQL queries, and the frequent need to create large batches of records in ACID compliant transactions, efficient resource management is crucial. The web application that has characteristics like those just mentioned, if it is going to bring deliver responsive and reliable services to its user community, must be managed with high intention.  Among the things that must be managed are threads. (Self-managing web applications for large user bases is a nice idea. But at the time of this writing, my peers in the software development industry are not declaring victories in this area.) In Java-based web applications, threads play a pivotal role in handling concurrent requests, performing background tasks, and ensuring that the application remains responsive under high loads.

When thread management is either ignored or handled improperly, issues ensue. What kind of issues?

  • Thread / Memory Leaks — Thread leaks occur when threads are not properly terminated or returned to the thread pool. Does it matter? Yes! If the threads are not being properly terminated or returned to the thread pool, and they are being created as the application runs, threads are leaking out. This will lead to a depletion of available threads, causing the application to hang or crash. (Eventually there are no threads are left to handle incoming requests.) How does this happen? This could be due to spend thrifty creation of threads in our code. Each thread uses a chunk of memory. Excessive creation of threads without proper management will exhaust the JVM heap space and lead to OutOfMemoryError exceptions. (Practically speaking, not too long after you see these exceptions in log files, your application is going to crash or become unstable.)
  • Thread Starvation and Increased Latency — This happens when lower-priority threads are perpetually prevented from executing because higher-priority threads monopolize the CPU. These low prior threads are not altogether unimportant. But when they are forced to wait on resource hogging threads, their unimportant work eventually becomes urgent. Making them wait invariably leads to unresponsive services and missed deadlines for critical tasks. Users may see the symptoms in slow application response times.
  • Unexpected Behavior — Poorly managed threads can cause the application to behave unpredictably under different load conditions. This makes it difficult to ensure consistent performance and reliability, especially in a production environment. Inconsistent State: If a ThreadLocal variable is not properly initialized for each thread, different threads may see different states, leading to inconsistent behavior in the application. (I experienced this woe while working on an application written for a government agency. The mismanagement of ThreadLocal variables in Liferay kept manifesting itself in application users getting sessions that actually belonged to someone else. The menus of the application were determined by the security role associated with the user’s account. The security role was stored in the user’s session. Without warning a user would suddenly have the menu for another user with more or less privileges than themselves. No, I did not write that code. But I still had to fix it.) Inheritance Issues: Using InheritableThreadLocal can lead to unexpected behavior if child threads inadvertently inherit values from parent threads when such inheritance is not intended.

This post delves into the essentials of thread management in Java-based web applications that run on Apache Tomcat. In the discussion that follows we will give special attention to (1) enumerating threads, (2) checking for threads that require cleanup or termination, and (3) special issues associated with Threadlocal variables.

Enumerating the Threads in Your Web Application

Getting a list of all threads in a web application is very simple. I will show you two ways to do it. I will demonstrate getting the list of threads in a Java-based web application running in a standard servlet container. (This solution will run in Jetty, Apache Tomcat, Apache JBoss (WildFly), GlassFish, IBM WebSphere, or Oracle WebLogic.)

Step 1: Create a Thread-Enumerating Servlet

By creating the enumeration solution as a servlet you will make it easier to get the results. (Yes, you could write it to catalina.out. However, you may have to ask an administrator for the file. And the contents may contain a lot more than you need, want, or have permission to see.)

package org.roderickbarnes.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

@WebServlet("/enumerateThreads")
public class ThreadEnumerationServlet extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
        // Tell the calling client what type of content will be returned (This is the mime type).
        httpServletResponse.setContentType("text/plain");
        PrintWriter printWriter = httpServletResponse.getWriter();

        // Get all stack traces
        Map<Thread, StackTraceElement[]> mapOfThreadToStackTraces = Thread.getAllStackTraces();
        for (Map.Entry<Thread, StackTraceElement[]> mapEntry : mapOfThreadToStackTraces .entrySet()) {
            Thread thread = mapEntry.getKey();
            StackTraceElement[] arrayOfStackTraceElement = mapEntry.getValue();
            
            printWriter.println("Thread Name: " + thread.getName());
            printWriter.println("Thread ID: " + thread.getId());
            printWriter.println("Thread State: " + thread.getState());
            printWriter.println("Thread Priority: " + thread.getPriority());
            printWriter.println("Is Daemon: " + thread.isDaemon());
            
            printWriter.println("Stack Trace:");
            for (StackTraceElement stackTraceElement : arrayOfStackTraceElement) {
                out.println("\t" + stackTraceElement);
            }
            printWriter.println("--------------------------------------------------");
        }
        printWriter.close();
    }
}

Listing 1 – Servlet for listing threads in a web application.

The doGet method in the servlet fetches all live threads and their stack traces using Thread.getAllStackTraces(). It then prints the details of each thread to the servlet response. This step is an easy one. You can create your own glorious code. But move your thread management goals forward faster by copying the code above and pasting it into your IDE of choice.

Step 2: Registering and Deploying the Thread-Enumerating Servlet

Unless you are using annotations, update theweb.xmlof your web application or servlet container. An example is provided in Listing 2.

<servlet>
    <servlet-name>ThreadEnumerationServlet</servlet-name>
    <servlet-class>com.example.ThreadEnumerationServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ThreadEnumerationServlet</servlet-name>
    <url-pattern>/enumerateThreads</url-pattern>
</servlet-mapping>

Listing 2 – Servlet deployment XML required for the web.xml file.

Deploy the web Application by doing the following:

  • Package your web application (WAR file) and deploy it to your servlet container server.
  • Ensure the servlet is correctly placed in the appropriate package (org.roderickbarnes.servlet in this case).

Step 3: Call the Servlet from Your Browser

Once deployed, you can access the servlet by navigating to http://your-server:port/your-app/enumerateThreads in your web browser. This will output the details of all active threads in your Tomcat application.

Pulling the Hanging Threads

Pulling Unstopped Threads

If you are creating threads manually, consider using ExecutorService from the java.util.concurrent package. This provides a better abstraction for managing threads, and you can easily shut down the executor service during application shutdown. Here are some of the benefits of using ExecutorService in your web application:

  • Thread Management – ExecutorService provides a clean and efficient way to manage a pool of threads, avoiding the overhead and risks associated with manually creating and managing threads. That is what this whole article is about. Using this service is a major move toward better thread management.
  • Graceful Shutdown – Proper handling of thread shutdown ensures that tasks are completed or terminated correctly, preventing resource leaks. ExecutorService facilitates graceful shutdown of your threads.
  • Concurrency Control – For those of us with a tendency toward micromanagement, the ExecutorService is a friend. You can control the number of concurrent tasks by configuring the thread pool size.

How would we use this service. Here below I provide you with the steps required to employ ExecutorService in the management of threads for your web application.

Step 1: Create a Thread Management Servlet that Uses ExecutorService

package org.roderickbarnes.servlet;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@WebServlet("/executeTask")
public class TaskExecutorServlet extends HttpServlet {

    private ExecutorService executorService;

    private void setExecutorService(ExecutorService executorServiceNew) {
        this.executorService = executorServiceNew;
    }

    private ExecutorService getExecutorService() {
        return this.executorService;
    }

    @Override
    public void init() {
        // Initialize the ExecutorService with a fixed thread pool
        executorServiceNew = Executors.newFixedThreadPool(17);

        this.setExecutorService(executorServiceNew);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse httpServletResponse) throws IOException {
        // Submit a task to the executor service
        this.getExecutorService().submit(() -> {
            try {
                // Simulate a task
                System.out.println("Task executed by thread: " + Thread.currentThread().getName());
                TimeUnit.SECONDS.sleep(2); // Simulate work with a sleep
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                e.printStackTrace();
            }
        });

        httpServletResponse.getWriter().write("Task submitted");
    }

    @Override
    public void destroy() {
        // Shutdown the ExecutorService when the servlet is destroyed
        this.getExecutorService().shutdown();
        try {
            if (!this.getExecutorService().awaitTermination(60, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
                if (!this.getExecutorService().awaitTermination(60, TimeUnit.SECONDS)) {
                    System.err.println("ExecutorService did not terminate");
                }
            }
        } catch (InterruptedException ie) {
            this.getExecutorService().shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

Listing 3 – Demonstrating the use of ExecutorService to manage threads

Step 2: Add a ServletContextListener

To ensure proper cleanup and initialization, it’s a good idea to use a ServletContextListener that handles the lifecycle of the ExecutorService. Note: This is not required but is recommended.

 

package org.roderickbarnes.servlet;

@WebListener
public class ExecutorServiceListener implements ServletContextListener {

    private ExecutorService executorService;

    private void setExecutorService(ExecutorService executorServiceNew) { 
        this.executorService = executorServiceNew; 
    } 

    private ExecutorService getExecutorService() { 
        return this.executorService; 
    }
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // Initialize the ExecutorService when the web application starts
        executorServiceNew = Executors.newFixedThreadPool(10);
        this.setExecutorService(executorServiceNew);
        sce.getServletContext().setAttribute("executorService", this.getExecutorService());
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // Shutdown the ExecutorService when the web application stops
        ExecutorService executorServiceTemp = (ExecutorService) sce.getServletContext().getAttribute("executorService");
        if (executorServiceTemp != null) {
            executorServiceTemp.shutdown();
            try {
                if (!executorServiceTemp.awaitTermination(60, TimeUnit.SECONDS)) {
                    executorServiceTemp.shutdownNow();
                    if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                        System.err.println("ExecutorService did not terminate");
                    }
                }
            } catch (InterruptedException ie) {
                executorServiceTemp.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
}

Listing 4 – Demonstrating the use of ExecutorService to manage threads

Why is this a good practice? The ServletContextListener provides a centralized place (1) to initialize the ExecutorService when the web application starts and (2) to properly shut it down when the application stops. This ensures that the ExecutorService is consistently managed throughout the application’s lifecycle.

Step 3: Update your web.xml if you are not using annotations.

<web-app>
    <servlet>
        <servlet-name>TaskExecutorServlet</servlet-name>
        <servlet-class>org.roderickbarnes.TaskExecutorServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TaskExecutorServlet</servlet-name>
        <url-pattern>/executeTask</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>org.roderickbarnes.ExecutorServiceListener</listener-class>
    </listener>
</web-app>

Listing 5 – Demonstrating the use of ExecutorService to manage threads

But how does all this work. Here, let me explain. There are four parts worth noting.

The Servlet Initialization Part – When the servlet is initialized (init method), an ExecutorService is created with a fixed thread pool of 17 threads. This means that up to 17 tasks can be executed concurrently.

The Handling Requests Part – Each time a request is made to the servlet’s /executeTask endpoint, a new task is submitted to the ExecutorService. The task simulates some work by sleeping for 2 seconds. In your web application you would have something that needs to be c concurrent and is germane to the user community or application’s needs.

The Servlet Destruction Part – When the servlet is destroyed (e.g., when the application is undeployed or the server is shut down), the ExecutorService is properly shut down. This ensures that all threads are terminated gracefully, avoiding potential memory leaks. Did you get that part?

The Context Listener Part (Optional) – The ExecutorServiceListener manages the lifecycle of the ExecutorService at the application level, ensuring it is available throughout the application’s lifecycle and cleaned up properly when the application is stopped.

Pulling Threads Hanging Due to ThreadLocal Variables Not Being Cleaned Up

Wherever you use ThreadLocal variables, make sure to call ThreadLocal.remove() when the variable is no longer needed, especially in the cleanup code of your application (e.g., in ServletContextListener or a similar lifecycle hook).

ThreadLocal<MyObject> threadLocalOfMyObject = new ThreadLocal<MyObject>();

try {
    // Setup the ThreadLocal object.
    threadLocalOfMyObject.set(new MyObject());

    // Use the ThreadLocal object.
} finally {
    threadLocalOfMyObject .remove();
}

Listing 6 – Using a Try-Catch Block to Ensure Removal of ThreadLocal Variables

Conclusion

This article has introduced you to some ways you can remediate thread issues in your web application. The ideas suggested here are not panaceas by any means. They are a few of many means for getting threads under control and bringing high intentionality to the management of resources. Among the things that should be considered are using the ExecutorService and ensuring that ThreadLocal variables are properly cleaned up. Before getting started with any plan to change how threads are being handled, use a tool like the one provided in Listing 1 to get your thread inventory.

In His grip by His grace,
Roderick L. Barnes, Sr.

In the Aftermath of Chastening Part 2 (Acts 5:12-16)

Continuity of Miraculous Power (Acts 5:12a)

With the conjunction and of and through the apostles hands (δὲ τῶν χειρῶν τῶν ἀποστόλων) of Acts 5:12, the material following the tragedy of Ananias and Sapphira (Acts 5:1-11) is tied to the record of what follows (Acts 5:12-16). In effect, using the coordinating conjunction, Luke tells the reader to look at Acts 5:12-16 in light of what has just happened and to see it as a continuation of the Spirit’s work. Notice the continuity.

Do not miss the fact that the power of the apostle’s anointing continued to be at work with many signs and wonders being done among the people. Do not miss the significance of their continued ability to do miracles.

The same Spirit that was at work in the separation of the liars is still at work in the support of the leaders.

Their credentials as approved men of God and authorities to whom the people must listen were in the many signs and wonders (John 10:38; 14:11). If you were struggling with what had happened, your confidence in the apostles would be restored daily by their godly character and their great ongoing power and willingness to help others free of charge. Through the continuity of miracles through the apostles, Christ was telling the church that He continued to be at work both in and through the apostles and that He approved of the outcome with Ananias and Sapphira.

Continuity of Unified Fellowship (Acts 5:12b)

See their cohesion and oneness; the people continued to be unified as a fellowship. It says that they were all with one accord in Solomon’s Porch. In light of verse 13 the all is certainly a reference to the known congregation prior to the event of Acts 5:1-11. That same group of people, minus two, is still meeting in Solomon’s Portico or colonnade.

Figure 1: Solomon’s Porch Concept Art – Covered area with columns

Thousands of people have come to faith since Pentecost; the outpouring of the Spirit was in a room where a 120 people could meet. There are too many people to meet in the upper room mentioned in Acts 2. The apostles have taken up the practice of Jesus (John 10:23); they go to an open place in the temple to meet with the people in a ministry of teaching and miracles.

Unity remained and the custom of coming together in the temple to hear the word continued. When the Lord cleanses His community, the problem is removed, and the people continue in unity. If a church community disintegrates on account of disobedience, it may be an indicator that the Lord is removing the lampstand (Matthew 5:13-16; Revelation 2:5) of that fellowship. Unity is important and after a tragic event it must be guarded and promoted. Why is unity important?

Unity is an indispensable attribute of fellowships that will be effective as witnesses in their communities (Acts 1:8; John 13:35; 17:21) and in the work for which we were saved (Ephesians 2:10; 4:15-16 Galatians 6:2). The ongoing unity made the Jerusalem fellowship fit for witnessing to the world and the work of building up one another. Prince among preachers, Charles Spurgeon (June 19, 1834 – January 31, 1892), puts the importance of unity in perspective:

Satan always hates Christian fellowship; it is his policy to keep Christians apart. Anything which can divide saints from one another he delights in. He attaches far more importance to godly fellowship than we do. Since union is strength, he does his best to promote separation. (Spurgeon, 1868).

The events of Acts 5:1-11 (chastening or church discipline) and Acts 5:12-16 (continued power and unity) are a lesson for the modern church. We are prone to permit and tacitly promote evil when we do not take an active stand against it in our fellowships. Why? We are fearful that we will lose membership, lose financial stability, and lose our ability to reach the surrounding community. But the truth is that the compromise of not confronting and cutting out willful sinning will grieve the Spirit and hence undermine out witness. We cannot bear fruit if we do not abide in His word. Acts 5:1-16 is telling our churches to not believe the lie of losing the church if we deal with sin. The truth is that we will lose our churches if we don’t deal with willful disobedience.

Evaluate and Embrace or EliminatePeople and things that underscore the importance of unity and undertake the ongoing challenge to protect and promote Christ-centered unity in our churches are of the Spirit and missional in nature. People and things that persistently undermine church unity are demonic and are used by the devil in his dogged determination to destroy men and the mission given the local church. Take inventory church. Evaluate and embrace everything that is found to be in the first category. Eliminate with extreme prejudice everything that falls into the second and everyone that, when confronted, will not repent.

In this regard I am especially qualified to say something. My journey with Jesus has included highs in ministry and times of dealing with disobedience in ways that have been painful, public, and yet absolutely necessary for the health of the fellowship… and my own walk with God. Now I am thankful. In the handling of sin in our fellowships we cannot forget the importance of grace, gentleness, and the goal of restoration. Let nothing be done toward the sinning brother or sister that does not take into account God’s grace toward us in Christ (Ephesians 4:32); recipients of grace must not forget their own history of rebellion and the great grace that brought about their repentance. Gentleness, if possible, should be shown toward those who have failed. Only when the sinning persons demonstrates an unwillingness to repent should fellowship be shut off and interactions be limited to what is absolutely necessary. Finally, we should aim for restoration. That means, although a period of separation or being sidelined is in order, we want to see our brothers and sisters back in fellowship and using their gifts for the glory of God and the good of others. Peter failed. After a time he was restored. The brother in Corinth failed. He needed to be put out for a time. But not permanently. He needed to be restored. Restoration should become part of our stories; otherwise our churches become characterized by the false notion that the members have not messed up and that failure is unforgivable and the end of fellowship — an anti-gospel of sorts.

Questions for Consideration

  1. Is the fear of repercussions preventing your fellowship from confronting sin issues in the congregation?
  2. Does the church have a history of helping a fallen brother or sister get back up?
  3. What message does it send to the surrounding community if the person who fails is sent away permanently?

References

Spurgeon, Charles H. (1868). Lectures to My Students. Marshall, Morgan & Scott.

In the Aftermath of Chastening Part 1 (Acts 5:12-16)

In the Aftermath of Chastening (Acts 5:12-16)

12 And through the hands of the apostles many signs and wonders were done among the people. And they were all with one accord in Solomon’s Porch. 13 Yet none of the rest dared join them, but the people esteemed them highly. 14 And believers were increasingly added to the Lord, multitudes of both men and women, 15 so that they brought the sick out into the streets and laid them on beds and couches, that at least the shadow of Peter passing by might fall on some of them. 16 Also a multitude gathered from the surrounding cities to Jerusalem, bringing sick people and those who were tormented by unclean spirits, and they were all healed.

Introduction

What does a congregation do after events like the church discipline displayed with Ananias and Sapphira (Acts 5:1-11)? You could stop everything and get a consultant / counselor to come in and help everyone deal with the grief and fear that comes with (1) lying to the Spirit and (2) the Spirit’s abrupt removal of the liars. You could lose momentum and eventually have to shut things down. (In the denominations that I have served in such a response would involve contacting the district because the assets of the church actually belong to the denomination.) If you were in the Ananias camp you could convene a clandestine committee to replace Peter. (In light of most recent events, Peter is probably going to know. And may the Lord have mercy on you when you come to church.) Here is what the passage promotes:

1) Regard the church community and its individual members as sacred; do not bring into the bride of Christ worldly ways of getting ahead.

2) Acknowledge the anointing and authority of those appointed to lead. In the case of the apostles, their position and power in God’s work makes lying to them tantamount to lying to the Holy Spirit.

But what does a fellowship do after events like those recorded in Acts 5:1-11? In the writing of Luke we see that some things continue without change and one thing does not remain the same.

Questions for Consideration

  1. Do you interact with your local congregation as a sacred community or something common?
  2. While our local church leaders are not supernaturally able to discern the truth about things on their own, the Spirit can give them insights into things that would not otherwise be known. In your work with your leadership and other Christians are you mindful of the Spirit’s presence?

Circle of Fifths Studies

Using the Circle of Fifths to Find 1-4-5 Chords

Majors and Relative Minors

Using the Circle of Fifths to Create Compositions

Major Scale for a Given Key
The Key C D
The First Three Chords are Major Chords F, C, G G, D, A
The Second Three Chords are Minor Chords D, A, E Em, Bm, F#m
The Last Chord is the Diminished Chord B D

 

References

Sherrill, Brian. (2021, April 9). Circle of Fifths Explained (for Guitar) [Video]. https://www.youtube.com/watch?v=qF3mJzDulJ8

Dealing with Disrespect

Are you regularly being disrespected by someone? Do you want to know why? Have a seat.
The content of their heart is being made manifest. “As a man thinketh in his heart, so is he.” (Proverbs 23:7) They are disrespectful because they are full of disrespect. The overflow or outworking of what is in their heart becomes obvious in conversation, obvious in conduct, and obvious in a continual disregard for your person.
What do you do in a situation like this? Forgive. Forgive them even as God through Christ has forgiven you (Ephesians 4:32). (Remembering the ways I have disrespected God helps me to forgive those who disrespect me. Remembering His forgiveness helps me put their trespass in perspective. History says, when I am willing to admit it, I am not better than the person disrespecting me.) Love. Love them in high quality service that is aimed at pleasing God and promoting faith in Christ. Respect. Respect them even if they disrespect you. Do not stoop to their level or take a break from following Jesus on account of their bad behavior. And then, if God allows, respectfully and humbly remove yourself from the situation.
In church history there are examples of people that were mistreated and but still returned kindness. They were disrespected and yet remained undaunted in doing right by their assailants. Here are three of them:
  • Joseph (Genesis 50:20) – He was sold into slavery by his brothers. Later he chose to deal with them through the perspective of his purpose and God’s grace.
  • David (1 Samuel 24:3-7) – The shepherd boy was relentlessly hunted by an insecure leader. Instead of making the most of his enemy’s vulnerable moment, David extends grace based on his reverence for God. Although repeatedly disrespected, David treats Saul with dignity and respect.
  • Stephen (Acts 6-7) – This man is the first recorded martyr of the church. When he is being falsely accused and then executed, he offers forgiveness. Notice that Stephen offers forgiveness not based on perfect apologies but based on the leading of the Spirit of Christ in Him.
Doing right by people who are doing us wrong is important. Showing kindness when people are unkind is part of the calling that is on our lives (1 Peter 3:9; Matthew 5:44). For those of us following Jesus, this is our family heritage and the mind and manner of Christ Himself (Isaiah 53:7; 1 Peter 2:23; Matthew 27:12-14).
In His grip by His grace,
Roderick L. Barnes, Sr.
P.S. Let no one think that the author of this post is above what is being written. My stuff stinks too. There are times when I am the person that has to repent of being disrespectful.

Missional Living — Being Relevant (Acts 5:17-21)

What do you do when godly people are being mistreated for believing in Jesus? What do you do when a men are incarcerated for daring to tell the truth about the fallenness of humanity, the great grace of God toward Man through the Son, and the availability of forgiveness and new life through faith? Our answer to this question is an indicator of whether or not our faith is functional and relevant or dysfunctional and inconsequential. Before you recoil at that statement and set this book aside forever, read this chapter. If, after reading this, you do not agree with what is being presented here, I will personally refund the money you paid for this book.

The Reaction of the Religious (Acts 5:17-18; John 12:42-43)

17 Then the high priest rose up, and all those who were with him (which is the sect of the Sadducees), and they were filled with indignation, 18 and laid their hands on the apostles and put them in the common prison.

This is now the second time the Sadducees, a group of people that do not believe in the resurrection (Matthew 22:23; Luke 20:27; Acts 23:8), have been provoked. Once again they have been incited into action by the preaching and teaching ministries of the apostles. This is the second time the apostles have irked them. In the first instance the marvelous healing and subsequent rejoicing of a well-known temple beggar occasioned an audience (Acts 3:7-10). Peter and John publicly refused to accept credit and attributed the miracle to the power of the risen Jesus of Nazareth (Acts 3:12-16). The crowd is listening to the apostles as they used the platform created by the healing to proclaim the gospel. During the preaching that followed the captain of the temple seized upon Peter and John and put them in custody until the next day (Acts 4:1-3). However, when brought out for a trial, Peter did some seizing of his own; the fisher of men seized the moment for the glory of God. In bold fashion the Galilean’s response to the question of how the man was healed

(i) indicts Israel’s leadership for the murder of the Lord (Acts 4:10),

(ii) declares the resurrection of Jesus and His position of prophesied importance (Acts 4:11) , and

(iii) promotes forgiveness of sins through faith in Jesus Himself (Acts 4:12).

In that first case the Sanhedrin did not repent. Instead they commanded the ignorant and untrained cult leaders (Acts 4:13) to stop witnessing for Jesus (Acts 4:17-18). Do you remember how Peter responded? Peter made it clear that he was not going to keep that command (Acts 4:19-20) and so, in the face of the blatant disregard for their directive, they threatened him… and then let he and John go (Acts 4:21).

Acts 5:17 — Here we are again. But it is worse this time. The same group, the high priest and all those who were with him (which is the sect of the Sadducees) have been watching as the prohibition on preaching Jesus went unheeded. Teaching and preaching keep happening. That is, the apostles continue declaring (1) that Jesus is the Christ promised by God through the prophets and validated by God through miracles signs and wonders, (2) forgiveness is available to everyone who repents and comes to God through faith in Jesus, (3) resurrection from the dead to a reward lies ahead for those who have trusted Jesus, and (4) the Holy Spirit is given to those who will obey God in the command to believe in Jesus (Ephesians 1:13). They were told to stop but did not. And now more people than ever know the truth. What truth?

  • The Truth about the Messiah – God has sent the Messiah in accordance with numerous prophecies. He was born of the seed of David (Luke 3:23-38), in the town of Bethlehem (Micah 5:2; Matthew 2:6; Luke 2:11), and through a virgin (Genesis 3:15; Isaiah 7:14). He was the rabble-rousing rabbi from Nazareth: Jesus.
  • The Truth about His Murder – He was crucified but was raised from the dead on the third day. When the leadership could not stop the growing influence of Jesus they colluded to have him put to death – the aforementioned crucifixion. Although he had committed no sin, Jesus was sentenced to die as a criminal in the shameful and painful death of a cross. The Roman official Pontius Pilate, realizing that Jesus was innocent, tried to let him go. The Sadducees (and Pharisees) were not having it. The religious leaders guided the people into demanding Jesus’ death (Matthew 27:20; Mark 15:11; Luke 23:13-23).

It was too much for people who were preoccupied with the self-promotion and protection of their own vain glory (John 12:42-43). Upon hearing that the Galileans were still promoting the resurrection, railing against their murder of the Christ, and preaching to get decisions about Jesus, they are filled with indignation (ζήλουJohn 2:17; Acts 13:35). They cannot bear the assertions about the ousted Rabbi and are wholly unprepared for the brazen disregard for their authority, the bold disrespect of teaching a forbidden doctrine in their house, and the lambasting declaration that they are murderers.

Here we are again. But this time it is different. How? Notice, friend, that in the company of people coming into Solomon’s colonnade is the high priest himself. This is new; he did not come with the arresting party last time. This time he is not delegating the operation to the temple captain and his law-enforcing cohort. His anger is so hot that he has personally come to help make the arrest and make sure that they get all of the apostles – not just Peter and John.

18 and laid their hands on the apostles and put them in the common prison.

Acts 5:18 — Having apprehended the rebellion leadership they put them in the common prison (τηρήσει δημοσίᾳ). It could be that the prior place of imprisonment was full or not large enough for the twelve. However, I believe that it was likely an attempt to make a public example of the apostle’s defiance. This will prove to be a mistake.

The Relevance in the Rescue (Acts 5:19-20)

19 But at night an angel of the Lord opened the prison doors and brought them out, and said, 20 “Go, stand in the temple and speak to the people all the words of this life.”

An angel of the Lord briefly enters the narrative. The but of Acts 5:19 tells the reader that the angel’s actions are to be seen as a response to the imprisonment. Who is he? Is it Gabriel? He does have a history of bringing a message of encouragement to people that are distraught or needing answers (Daniel 8:15-17; 9:21-23; Luke 1:11-13; 18-19; 26-28). We are not given a name. In fact, Luke is especially frugal in describing the apostles’ visitor. There is no mention made of his name, no intimation of a shining face (Matthew 28:3), and no hint of amazing apparel (Mark 16:5; John 20:12; Luke 24:4; Acts 1:10). But what he does say goes beyond the mere relating of historical events to challenge and encourage us today. The angel, a servant of God ministering to those who will inherit salvation (Hebrews 1:14), provides a practical example of what to do for our brothers and sisters in peril.

  • He was Real in their Misery — They have the indwelling Holy Spirit. And so they are not alone (John 14:18). And the Lord has the power to speak a word and make something happen from a distance; the prison could have been opened remotely. And the message given them could have been communicated with dreams and visions. But at this time these men do not need a vision; they need a visit. Their public incarceration was personal. More than a vision they need a visitor. Someone needs to go in person out of their way to see them in prison.
  • He Released Them — The ministry of this ministering spirit goes beyond an appearance and words of encouragement. Their problem is not psychological. Our apostles are not theologically incarcerated. These men of God are actually incarcerated and what they need, in order to be effective witnesses at this time, is to be released. These men do not need hypothetical help or mere words; they require a liberation. The angel brings actual aid in the form of a real release.
  • He Reminded Them of Their Mission — The spirit indeed is willing but the flesh is weak. And where it seems unnecessary to say certain things, it is certain that certain things need to be said. Perhaps some of these men have never been to jail. And maybe some of them have never been handled roughly. It would be easy for them to get caught up in the turmoil of their own emotions and take some time to recuperate. But Heaven has a point to make and these men need to make their appointment. The world has need of their words (John 17:18-20; Luke 10:16; John 21:15-17). The angel directs them to get back to the work they were called to, the work needed by the people, the ministry of speaking the words of this life.

It is not enough to tell people that we are praying for them. It is not enough to wish that people get well, or to want them to be encouraged during their incarceration (or hospitalization). It is not enough to send money. There comes a time for those who name the name of Christ to get up from the pews and go to the place where their brethren are being held. Why? To speak words of encouragement. To remind them that they are loved on earth as well as in Heaven (Matthew 25:36). And, if it is proper and possible, to set them free.

Figure 1 – What would it look like for you to visit someone in prison and be an encouragement?

Questions for Consideration

  1. Do I know of anyone that is currently incarcerated for their faith in Christ, suffering for serving Jesus, or dealing with the consequences of godly civil disobedience? Is it that there is no one or that I have not taken the time to find out who they are and where they are?
  2. What does God want me to do for those who are in trouble? The answer is seen in Jesus Himself (John 3:16; Matthew 20:28) and the angel of this passage.
  3. If I cannot go to the persons in peril or prison, what others ways can reach them with relevant aid and encouragement to remain engaged in what God has called them to do?

The Righteous Rebellion and the Clueless Council (Acts 5:21)

21 And when they heard that, they entered the temple early in the morning and taught. But the high priest and those with him came and called the council together, with all the elders of the children of Israel, and sent to the prison to have them brought.

The visit was not in vain. The apostles heard the words and heeded them. There would be no retreating to recuperate. Instead there would be a relentless charge against the gates of hell through the spoken word (Acts 5:20). The lesson of Lazarus was with the Lord’s men. They are now living in the fulness of a righteous rebellion. And what about the hard-nosed high priest and his council?

[T]he high priest and those with him are the Sadducees. Again, they are a group that does not believe in angels, spirits, or resurrection (Acts 23:8). All of those with the high priest are an ungodly clique clinging desperately to a weakening grip on the people; they are afraid of losing power (John 11:48). The disturbance that started with Jesus was not quelled with His execution. In has gotten worse. The troublemakers have been arrested and the Sadducees have called the council together, with all the elders of the children of Israel. We can imagine that they are seated in semicircle. Many of them are dressed in ornate and expensive long robes (Mark 12:38; Acts 22:20). This was the supreme court and legislative body in ancient Israel; this council (συνέδριον) is The Great Sanhedrin. It was composed of 71 members and included the high priest, the elders of the people, and a select group of scribes. This is new. Compare this gathering with the last time the high priest was present to judge the apostles. What changed?

  • Increased Arrests – In the prior gathering only two apostles were arrested: Peter and John. This time all of them have been arrested.
  • Increased Formality – In the prior gathering it was the high priest and his family (Acts 4:5) – Sadducees. This time it is the Sanhedrin. The two main doctrinal camps of the Jewish religious leadership are both present.

Tensions are escalating. The seriousness of the conflict and anger is growing. We have gone from an informal court of the high priest’s family and friends to a formal supreme court hearing. Now that the court membership has convened they are ready to bring the accused to stand trial. And so the Sanhedrin sent to the prison to have the apostles brought before them.

Just like Jesus, the apostles have an adversarial relationship with bad religious leadership. They were commanded to stop. But they have defied that decree. Just like Jesus, the apostles’ defiance and determination to persist in teaching the truth with signs supporting their message (Acts 4:30) is aggravating their adversaries and turning into a trial. And then there is you. Yes, you!

If you are following Jesus, this is where you are headed. But you don’t want conflict? Any attempt to have Christ and not have conflict with the world is futile (John 15:18; 2 Timothy 3:12). You cannot have one without the other. To be led by the Spirit of Christ is to be at odds with a world that is led by another spirit (Ephesians 2:2).

And do not miss that the council does not (1) receive the message or (2) know what God is doing for his messengers. They are like Herod looking for the Christ Child in the wrong places. They sent to have the apostles brought from the prison. But they are not in the prison. And, again, then there is you. Yes, you!

Attempts to control your message, cut off your ministry, and imprison the messenger only work insofar as God wants them to. He is the one in control. And you have one job. Be His witness (Acts 1:8). Be His witness before the people who want and need to hear the gospel. Be his witness before the court when called to give an answer for your ongoing efforts to promote Christ.

Questions for Consideration

  1. What can I expect to happen if I follow the example of Jesus and the apostles in declaring the truth?
  2. What is going to happen if I am told to stop preaching Christ? Bear in mind that the apostles received a special word on continuing in their ministry (Acts 5:20).
  3. Does the Lord care about the people that are trying to prevent gospel preaching (Ezekiel 18:23; 33:11; Luke 19:41-42)?

Jmix Timers and Web Application Usage Logging

Introduction

Logging and auditing are important aspects of web application security and monitoring. The former, when it is done well, makes the latter easy. That is, if our web applications feature good logging, it will be easier for us to audit the activity of users and system components. When we can efficiently (without great programming effort and with computational efficiency) audit when a user opened a screen, when they pressed a button, when they created a record, when they updated a record, when they deleted a record, and when they exited a screen, it is straightforward to answer questions about application usage. The dashboard seen in Figure 1 was created based on usage data captured in the background as users interact with a web application.

 

This post is a first look at using the Timer facet of Jmix to facilitate the automated capture of application module usage. It is a short read with documented code demonstrating an uncomplicated way to add auditing to your application today. By the end you will know how to do the following:

  • Add a logging service to your Spring Boot application
  • Capture log events and push them to the database
  • Ensure that the capture time is in the time of the user and not the database or application server.

The Logging Database Tables

We will put our logging events into a relational database. (In this post will will use PostgreSQL. However, you can use in RBDMS you like. Just make sure that you can find JDBC drivers that will work with your Spring Boot web application server.) We have four tables. They are shown in an ERD in the Figure 2.

Figure 2 — Jmix Logging ERD

The SQL script for creating these tables is shown in Listing 1.

 

CREATE TABLE IF NOT EXISTS bifref_application_component (
    application_component_id character varying(255) NOT NULL,
    application_component_type character varying(255) NOT NULL,
    name character varying(255) NOT NULL,
    description character varying(1000)
    CONSTRAINT pk_bifref_application_component PRIMARY KEY (application_component_id)
);

CREATE TABLE IF NOT EXISTS bifref_application_event(
    application_event_id uuid NOT NULL,
    application_event_type_id character varying(255) NOT NULL,
    username character varying(255) NOT NULL,
    event_start timestamp without time zone NOT NULL,
    event_stop timestamp without time zone NOT NULL,
    version integer NOT NULL,
    application_component_id character varying(255) NOT NULL,
    CONSTRAINT pk_bifref_application_event PRIMARY KEY (application_event_id),
    CONSTRAINT fk_bifref_application_component 
        FOREIGN KEY (application_component_id)
        REFERENCES bifref_application_component (application_component_id) 
        MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION,
    CONSTRAINT fk_bifref_application_event_type 
        FOREIGN KEY (application_event_type_id)
        REFERENCES bifref_application_event_type (application_event_type_id) 
        MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
);

CREATE TABLE IF NOT EXISTS bifref_application_event_type (
     application_event_type_id character varying(255) NOT NULL,
     name character varying(255) NOT NULL, 
     description character varying(1000),
     CONSTRAINT pk_bifref_application_event_type PRIMARY KEY (application_event_type_id)
);

Listing 1 – SQL script for creating logging tables.

The SQL script in Listing 1 will help you create the tables required for this post. You can rename them to whatever you want but need to remember that the names provided are part of a working solution. Also, the tables were modeled in Jmix’s data model visual designer. (It makes it easier to maintain the design if we leverage the design features of the Jmix plugin.)

The Logging Service in Spring Boot

Logging of application events is handled by a service. In Listing 2 we provide the code for an application event logging service.

package com.bif.azurereference.app;

import com.bif.azurereference.entity.ApplicationComponent;
import com.bif.azurereference.entity.ApplicationEvent;
import com.bif.azurereference.entity.ApplicationEventType;
import com.bif.azurereference.entity.EnumerationApplicationComponentType;
import io.jmix.core.DataManager;
import io.jmix.core.NoResultException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.UUID;

@Service("ApplicationEventLoggingService")
public class ApplicationEventLoggingService {

    @Autowired
    private DataManager dataManager;

    public DataManager getDataManager() {
        return this.dataManager;
    }

    public ApplicationEvent logApplicationEvent(
            UUID uuidApplicationEventID,
            String stringApplicationEventTypeID,
            String stringApplicationComponentID,
            String stringApplicationComponentType,
            String stringUsername,
            LocalDateTime localDateTimeEventStart,
            LocalDateTime localDateTimeEventStop
        ) {

        /**
         * Step 1: Load referenced application event type.
         */
        ApplicationEventType applicationEventType = null;
        try {
            applicationEventType = this.getDataManager().load(ApplicationEventType.class).id(stringApplicationEventTypeID).one();
        } catch (NoResultException noResultException) {
            System.out.println("No event type found for " + stringApplicationEventTypeID);
        }

        // If the event type does not exist, create it.
        if (applicationEventType == null) {

            applicationEventType = new ApplicationEventType();

            applicationEventType.setApplicationEventTypeID(stringApplicationEventTypeID);

            applicationEventType.setName(stringApplicationEventTypeID);
            applicationEventType.setDescription(stringApplicationEventTypeID);
            applicationEventType.setCreatedBy("admin");
            applicationEventType.setCreatedDate(OffsetDateTime.now());
            applicationEventType.setVersion(1);
            applicationEventType.setSortOrdinal(0);

            try {
                this.getDataManager().save(applicationEventType);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        }

        /**
         * Step 2: Load referenced application component.
         */
        ApplicationComponent applicationComponent = null;
        try {
            applicationComponent = this.getDataManager().load(ApplicationComponent.class).id(stringApplicationComponentID).one();
        } catch (NoResultException noResultException) {
            System.out.println("No component found for " + stringApplicationComponentID);
        }

        // If the application component does not exist, create it.
        if (applicationComponent == null) {
            applicationComponent = new ApplicationComponent();
            applicationComponent.setApplicationComponentID(stringApplicationComponentID);
            applicationComponent.setName(stringApplicationComponentID);
            applicationComponent.setDescription(stringApplicationComponentID);
            applicationComponent.setApplicationComponentType(EnumerationApplicationComponentType.fromId(stringApplicationComponentType));
            applicationComponent.setCreatedBy("admin");
            this.getDataManager().save(applicationComponent);
        }

        /**
         * Step 4: If a primary key was not passed, create it.
         */
        if (uuidApplicationEventID == null) {
            uuidApplicationEventID = UUID.randomUUID();
        }

        /**
         * Step 5: Create the object.
         */
        ApplicationEvent applicationEvent = this.getDataManager().create(ApplicationEvent.class);
        applicationEvent.setApplicationEventID(uuidApplicationEventID);
        applicationEvent.setApplicationEventTypeID(applicationEventType);
        applicationEvent.setApplicationComponentID(applicationComponent);
        applicationEvent.setEventStart(localDateTimeEventStart);
        applicationEvent.setEventStop(localDateTimeEventStop);
        applicationEvent.setUsername(stringUsername);

        /**
         * Step 6: Save the object.
         */
        this.getDataManager().save(applicationEvent);

        /**
         * Step 7: Return the object.
         */
        return applicationEvent;
    }

    public ApplicationEvent updateApplicationEvent(
            ApplicationEvent applicationEvent
    ) {
        /**
         * Step 1: Get the application event identifier.
         */
        UUID uuid = applicationEvent.getApplicationEventID();

        /**
         * Step 2: Find the application event in the database.
         */
        ApplicationEvent applicationEventTemp = this.getDataManager().load(ApplicationEvent.class).id(uuid).one();
        applicationEventTemp.setEventStop(applicationEvent.getEventStop());

        if (applicationEventTemp != null) {
            this.getDataManager().save(applicationEventTemp);
        }

        /**
         * Step 2: Return the object.
         */
        return applicationEventTemp;
    }
}

Listing 2 – Java Code for an application vent logging service.

The Timer and Capturing Usage Events

Timer is component of Jmix defined in the facets element an application screen. Specifically, it will be in the screen XML descriptor. The configuration of a Timer through the XML is done through three attributes: delay, autostart, and repeating.

Parameter Name Required? Desciption
delay Yes This is the timer interval in milliseconds.
autostart No indicates whether or not the timer will start automatically. The default setting is false; when autostart is set to false the timer will start only when its start() method is invoked. When it is set to true, the timer starts immediately after the screen opening. This parameter is optional.
repeating No Turns on repeated executions of the timer. If the attribute is set to true, the timer runs in cycles at equal intervals defined in the delay attribute. Otherwise, the timer runs only once as many milliseconds as specified in the delay attribute after the timer start. This parameter is optional.

 

 

 

 

 

 

 

Ensure that Captured Time is in the Time of the User

 

Conclusion

 

References