eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Regression testing is an important step in the release process, to ensure that new code doesn't break the existing functionality. As the codebase evolves, we want to run these tests frequently to help catch any issues early on.

The best way to ensure these tests run frequently on an automated basis is, of course, to include them in the CI/CD pipeline. This way, the regression tests will execute automatically whenever we commit code to the repository.

In this tutorial, we'll see how to create regression tests using Selenium, and then include them in our pipeline using GitHub Actions:, to be run on the LambdaTest cloud grid:

>> How to Run Selenium Regression Tests With GitHub Actions

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Introduction

In this tutorial, we’ll take a look at the BaseX XML database. We’ll see what it is, how to use it and what we can do with it.

2. What Is BaseX?

BaseX is a lightweight, high-performance and scalable XML database. It allows us to store a large amount of data provided in XML format, and then allows us to query and manipulate it using XQuery and XPath.

BaseX offers us a number of different ways we can work with our data, including a GUI application, command line interface, and HTTP APIs, allowing us to provide complex XQuery processing.

3. Running BaseX

Now that we know what BaseX is for, we need to be able to run it. BaseX requires a Java 17 or newer JVM.

We can download the ZIP package from the BaseX download page. This provides everything we need to run BaseX. Once unpacked, we’re ready to start.

Within this package, we’ve got our full database. This includes:

  • In /bin, some scripts for starting the database in various ways.
  • In /data, the actual data that exists within our database.
  • In /lib and /webapp, the actual database software.
  • In /src and /repo, sources for XQuery scripts and modules.

Our BaseX installation can actually manage many separate databases. Each of these exists as a separate directory inside the /data directory.

4. Command Line Interface

BaseX comes with a command-line interface allowing us to work directly with our database. This is useful for administrative actions and quick queries of our data. However, this isn’t designed for concurrent access to a database. We’ll need to rely on the server HTTP APIs for that instead, as we’ll see later.

4.1. Starting the Command Line Interface

We can start the command line interface by executing the ./bin/basex or ./bin/basex.bat command from within our unpacked BaseX installation:

$ ./bin/basex
BaseX 12.0 [Standalone]
Try 'help' to get more information.
>

Once we’ve done this, we have an interface to directly access the databases in our installation.

4.2. Creating and Dropping Databases

We can create a new database using the CREATE DATABASE command:

> CREATE DATABASE baeldung
Database 'baeldung' created in 18.82 ms.

By default, this will create an empty database. However, we can also provide a data file to store in the database:

> CREATE DATABASE baeldung https://files.basex.org/xml/factbook.xml
Database 'baeldung' created in 734.75 ms.

This file can either be locally accessible or on an HTTP URL. The BaseX database will download the file if needed and store it in the new database.

We can now use the LIST command to see our newly created database:

> LIST
Name      Resources  Size     Input Path
----------------------------------------------------------------------
baeldung  1          2304048  https://files.basex.org/xml/factbook.xml

1 database(s).

If we’ve got a database that we don’t want any more, we can drop it with the DROP DATABASE command:

> DROP DATABASE baeldung
Database 'baeldung' was dropped.

Once this is done, the database is immediately dropped.

4.3. Opening a Database

Instead of creating a new database, we often need to access one that already exists. This is done using the OPEN command, specifying the name of the database:

> OPEN baeldung
Database 'baeldung' was opened in 26.67 ms.

Once done, all of our commands are now executed within the context of this database.

When a database is created, it’s also automatically opened for us, so we don’t need to do this in that case.

We can also use the INFO DATABASE command to see which database is currently open:

> INFO DATABASE
Database Properties
 NAME: baeldung
 SIZE: 2251 kB
 NODES: 104627
 DOCUMENTS: 1
 BINARIES: 0
 VALUES: 0
 TIMESTAMP: 2025-10-22T06:40:31.403Z
 UPTODATE: true

This can be useful if we’re switching between databases and need to check where we are at any given time.

4.4. Managing Resources

Now we’ve got a database, we need to add some data to it. All of the data in our database comes in the form of XML files, and there’s no requirement that these different XML files have the same schema. We’re able to store whatever data we have in it, and then we can work with it all.

We can add new files to our database using the ADD command:

> ADD https://files.basex.org/xml/xmark.xml
Resource(s) added in 510.38 ms.

When we do this, we can specify the filename in the same way we do for creating a new database.

All of the files in our database have a name. By default, this is the filename of the file that we’ve just added – xmark.xml in this case. If we want, we can specify the name to use when we add our file using ADD TO:

> ADD TO other.xml https://files.basex.org/xml/xmark.xml
Resource(s) added in 219.85 ms.

We can then see what files exist in our database using the DIR command:

> DIR
Input Path    Type  Content-Type     Size
-------------------------------------------
factbook.xml  xml   application/xml  104627
other.xml     xml   application/xml  5256
xmark.xml     xml   application/xml  5256

3 entries.

If we need to, we can also delete files from our database using the DELETE command:

> DELETE other.xml
1 resource(s) deleted in 3.88 ms.

For this, we need to know the name that the file has within our database. Once we’ve done this, the data is permanently removed and can’t be used any more.

4.5. Querying Resources

Once we’ve got our database with data in it, we need to be able to query this data. We can do this with the XQUERY command. This takes an XQuery query that’s used to retrieve some data:

> XQUERY //item/name
<name>duteous nine eighteen </name>
...
<name>holds perhaps despair amorous </name>
Query "basex" executed in 21.15 ms.

This query is executed against every file in our database, and the matches from all of these are returned.

The matches returned can be as simple or complex as needed. In our above example, this was one element, but we can return entire element trees too if we need:

> xquery //city
<city id="f0_1461" country="f0_136" longitude="10.7" latitude="46.2">
  <name>Tirane</name>
  <population year="87">192000</population>
</city>
...
<city id="f0_36514" country="f0_136" longitude="20.1" latitude="41.1">
  <name>Elbasan</name>
  <population year="87">53000</population>
</city>
Query "basex" executed in 10.79 ms.

By default, this query will work across every file in the current database. If we want, we can specify a different database to access using the db:get() function:

> XQUERY db:get("baeldung")//item/name
<name>duteous nine eighteen </name>
...
<name>holds perhaps despair amorous </name>
Query "basex" executed in 10.0 ms.

Alternatively, we can target a single file within a database using the doc() function:

> XQUERY doc("baeldung/xmark.xml")//item/name
<name>duteous nine eighteen </name>
...
<name>holds perhaps despair amorous </name>
Query "basex" executed in 5.4 ms.

Doing this, we can explore the data as much as we want.

5. HTTP Interface

As well as the command line interface to manage our databases, BaseX also comes with an HTTP server that can expose our data in a variety of ways.

5.1. Starting the HTTP Server

We can start the HTTP server by executing the ./bin/basexhttp or ./bin/basexhttp.bat command from within our unpacked BaseX installation:

-> % ./bin/basexhttp
BaseX 12.0 [HTTP Server]
[main] INFO org.eclipse.jetty.server.Server - jetty-12.0.22; built: 2025-06-02T15:25:31.946Z; git: 335c9ab44a5591f0ea941bf350e139b8c4f5537c; jvm 21.0.2+13-LTS
[main] INFO org.eclipse.jetty.ee9.webapp.StandardDescriptorProcessor - NO JSP Support for /, did not find org.eclipse.jetty.ee9.jsp.JettyJspServlet
[main] INFO org.eclipse.jetty.session.DefaultSessionIdManager - Session workerName=node0
Server was started (port: 1984).
[main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started oeje9n.ContextHandler$CoreContextHandler@2c78d320{BaseX: The XML Database and XQuery Processor,/,b=file:///Users/coxg/source/me/baeldung/basex/webapp/,a=AVAILABLE,h=oeje9n.ContextHandler$CoreContextHandler$CoreToNestedHandler@132e0cc{STARTED}}
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@512baff6{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
[main] INFO org.eclipse.jetty.server.Server - Started oejs.Server@77fbd92c{STARTING}[12.0.22,sto=0] @613ms
HTTP Server was started (port: 8080).
HTTP STOP Server was started (port: 8081).

This actually starts three network servers, by default listening on ports 1984, 8080 and 8081. The one on port 8080 is the interesting one, because this is our HTTP server that we can send queries to.

5.2. Authentication

This server requires authentication to make sure our data is safe. By default, there’s an admin account with a password that’s generated the first time the HTTP server is started. We can find the password for this in the log files, located in /data/.logs:

$ cat data/.logs/2025-10-20.log
07:50:10.457	SERVER	admin	OK	Server was started (port: 1984).
07:50:10.505	SERVER	admin	INFO	Initial admin password (change after first login): 29a058d7-9dc3-4d7a-bab1-8380eca78e42

If we wish, we can change this using the PASSWORD command from the command line client:

> PASSWORD NewPassword
Password of user 'admin' changed.

All of our HTTP requests to the server need to provide credentials using HTTP basic authentication. These consist of our username – “admin” – and password, correctly encoded as expected for basic authentication. Our HTTP client should be able to handle this automatically for us.

5.3. Accessing Databases

We can list the available databases by making an HTTP call to the /rest endpoint on our server:

GET /rest HTTP/1.1
Authorization: Basic YWRtaW46TmV3UGFzc3dvcmQ=

The response will be an XML document describing all of the databases that we’ve created:

HTTP/1.1 200 OK
Content-Type: application/xml; charset=UTF-8
<databases xmlns="http://basex.org/rest">
  <database resources="3" size="2796460">baeldung</database>
</databases>

5.4. Accessing Resources

We can access a specific database by including it on the URL – for example, /rest/baeldung. If we call this directly, we’ll see a list of all the documents that have been added to our database:

GET /rest/baeldung HTTP/1.1
Authorization: Basic YWRtaW46TmV3UGFzc3dvcmQ=

---
HTTP/1.1 200 OK
Content-Type: application/xml; charset=UTF-8

<database xmlns="http://basex.org/rest" name="baeldung"> <resource type="xml" content-type="application/xml" size="104627">factbook.xml</resource> <resource type="xml" content-type="application/xml" size="5256">other.xml</resource> <resource type="xml" content-type="application/xml" size="5256">xmark.xml</resource> </database>

We can then access these resources directly by including them on the URL too – for example, /rest/baeldung/other.xml:

GET /rest/baeldung/other.xml HTTP/1.1
Authorization: Basic YWRtaW46TmV3UGFzc3dvcmQ=

---
HTTP/1.1 200 OK
Content-Type: application/xml; charset=UTF-8

<?xml version="1.0"?>
<site>
  <regions>
    <africa>
...
    </closed_auction>
  </closed_auctions>
</site>

5.5. Querying Resources

In addition to simply retrieving the entire resources that we’ve added to our database, we can execute queries against them to get back the data that we’re interested in.

We can do simple queries using the query parameter on our URL. We can do this either on a single resource or on the database as a whole:

GET /rest/baeldung?query=//item/name HTTP/1.1
Authorization: Basic YWRtaW46TmV3UGFzc3dvcmQ=

---
HTTP/1.1 200 OK

<name>duteous nine eighteen </name>
<name>great </name>
...
<name>practice space commune women </name>
<name>holds perhaps despair amorous </name>

Note that, in this case, we get back exactly the same as if we ran the query in the command-line client. This means it’s not a single XML document, but rather a stream of outputs from our query – in this case, a set of XML elements matching our query.

We can also provide more complicated XQuery queries as an HTTP POST call:

POST /rest/baeldung HTTP/1.1
Authorization: Basic YWRtaW46TmV3UGFzc3dvcmQ=
Content-Type: application/xml

<query xmlns="http://basex.org/rest">
  <text><![CDATA[ for $i in (//city/name)[position() <= 5] return string-length($i) ]]></text>
</query>

---
HTTP/1.1 200 OK

6
7
6
5
7

This query will return the lengths of the first five entries in the XPath //city/name, executed across the entire database. As before, this isn’t a single XML document but rather a stream of the values returned by our query.

5.6. Manipulating Resources

In addition to querying our resources, we’re also able to create and update them. We can do this with the PUT method to the desired resource, sending the entire XML resource as the request body:

PUT /rest/baeldung/new.xml HTTP/1.1
Authorization: Basic YWRtaW46VGhlUGFzc3dvcmQ=
Content-Type: application/xml

<?xml version="1.0" standalone="yes"?>
<site>
  <regions>
    <africa>
...
    </closed_auction>
  </closed_auctions>
</site>

If this resource already exists within the database, we’ll replace it. If it doesn’t already exist, we’ll create a new one instead.

We can delete resources in the same way, using the DELETE method on the resource:

DELETE /rest/baeldung/new.xml HTTP/1.1
Authorization: Basic YWRtaW46VGhlUGFzc3dvcmQ=

Once done, these changes are immediately available to query as with any other data in our database.

6. Summary

In this article, we’ve taken a very quick look at the BaseX database system. There’s a lot more that we can do with this system. Next time you need to query and manipulate large amounts of XML data for your applications, why not give it a try?

Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)