Rules and patterns for implementing plugin-internal Lucene search in a Lutece 8 plugin. Custom index, daemon, CDI events, batch processing. Based on the forms plugin pattern.
View on GitHubskills/lutece-lucene-indexer/SKILL.md
February 5, 2026
Select agents to install to:
npx add-skill https://github.com/lutece-platform/lutece-dev-plugin-claude/blob/main/skills/lutece-lucene-indexer/SKILL.md -a claude-code --skill lutece-lucene-indexerInstallation paths:
.claude/skills/lutece-lucene-indexer/# Lutece 8 Search Indexer
> Before implementing a search indexer, consult `~/.lutece-references/lutece-form-plugin-forms/src/java/fr/paris/lutece/plugins/forms/service/search/` — the reference implementation.
## Architecture Overview
```
IMyPluginSearchIndexer (interface)
↑ implements
LuceneMyPluginSearchIndexer (@ApplicationScoped, owns its Lucene index)
↓ triggered by
MyPluginSearchDaemon (declared in plugin.xml)
↓ fed by
EventListener (@ObservesAsync domain events → queues IndexerAction)
```
A plugin manages its own Lucene index independently from the core. This allows custom fields, sorting, filtering and dedicated search UI in the back-office.
## Step 1 — Indexer Interface
```java
public interface IEntitySearchIndexer
{
/**
* Index a single document (queues an action for the daemon)
*/
void indexDocument( int nIdEntity, int nIdTask, Plugin plugin );
/**
* Add an indexer action to the queue
*/
void addIndexerAction( int nIdEntity, int nIdTask, Plugin plugin );
/**
* Process queued actions (called by daemon)
*/
String incrementalIndexing( );
/**
* Rebuild the entire index (called by daemon on flag)
*/
String fullIndexing( );
/**
* Check if index is ready
*/
boolean isIndexerInitialized( );
}
```
## Step 2 — Lucene Indexer Implementation
```java
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.IntPoint;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.document.SortedDocValuesField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.util.BytesRef;
import fr.paris.lutece.portal.service.search.SearchItem;
@Application