Date: 2025-10-20
Issue: NedlastningService JSON filters don't work - downloaded 263,764 bruksenheter instead of ~100-200
// NedlastningService with JSON filter
String filter = "{\"kommunefilter\": [\"4601\"], \"matrikkelenhetfilter\": [123, 456, 789]}";
nedlastningService.findObjekterEtterId(cursor, Domainklasse.BRUKSENHET, filter, ...);Test Results (Bergen Kommune - 85 matrikkelenheter):
- Expected: ~100-200 bruksenheter
- Actually downloaded: 263,764 bruksenheter (ALL in kommune!)
- Conclusion:
matrikkelenhetfilteris completely ignored by the API
Step 1: BruksenhetService.findBruksenheterForMatrikkelenheter()
- Returns
MatrikkelenhetIdTilBruksenhetIdsMap(a map of matrikkelenhet ID → list of bruksenhet IDs) - This is a dedicated API method designed specifically for this purpose
Step 2: StoreService.getObjects()
- Takes
MatrikkelBubbleIdList(list of bruksenhet IDs) - Returns
MatrikkelBubbleObjectList(full Bruksenhet objects)
<execution>
<id>wsimport-bruksenhet</id>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlFiles>
<wsdlFile>BruksenhetServiceWS.wsdl</wsdlFile>
</wsdlFiles>
<packageName>no.matrikkel.client.generated.bruksenhet</packageName>
</configuration>
</execution>@Bean
public BruksenhetService bruksenhetService() {
// Configure with authentication, timeouts, endpoint URL
}
@Bean
public StoreService storeService() {
// Configure with authentication, timeouts, endpoint URL
}@Component
public class BruksenhetClientWrapper {
private final BruksenhetService bruksenhetService;
private final StoreService storeService;
public List<Bruksenhet> findBruksenheterForMatrikkelenheter(List<Long> matrikkelenhetIds) {
// Step 1: Get IDs from BruksenhetService
MatrikkelenhetIdList idList = ...;
MatrikkelenhetIdTilBruksenhetIdsMap resultMap =
bruksenhetService.findBruksenheterForMatrikkelenheter(idList, context);
// Extract all bruksenhet IDs from map
List<BruksenhetId> allBruksenhetIds = new ArrayList<>();
for (Entry entry : resultMap.getEntry()) {
allBruksenhetIds.addAll(entry.getValue().getItem());
}
// Step 2: Fetch full objects from StoreService
MatrikkelBubbleIdList bubbleIdList = ...;
MatrikkelBubbleObjectList objects = storeService.getObjects(bubbleIdList, context);
return objects;
}
}// OLD (NedlastningService - BROKEN)
List<Bruksenhet> bruksenheter = nedlastningClient
.findBruksenhetForMatrikkelenheter(kommunenummer, matrikkelenhetIds);
// NEW (BruksenhetService - WORKS!)
List<Bruksenhet> bruksenheter = bruksenhetClient
.findBruksenheterForMatrikkelenheter(matrikkelenhetIds);private MatrikkelContext createBruksenhetContext() {
MatrikkelContext context = new MatrikkelContext();
context.setLocale("no_NO");
// Koordinatsystem: EUREF89 UTM Sone 31 (Bergen)
KoordinatsystemKodeId koordinatsystem = new KoordinatsystemKodeId();
koordinatsystem.setValue(9);
context.setKoordinatsystemKodeId(koordinatsystem);
context.setSystemVersion("1.0");
context.setKlientIdentifikasjon(properties.getApi().getUsername());
// Far-future snapshot version avoids permission errors
Timestamp snapshotVersion = new Timestamp();
ZonedDateTime futureDate = ZonedDateTime.of(9999, 1, 1, 0, 0, 0, 0, ZoneId.of("Europe/Oslo"));
GregorianCalendar gcal = GregorianCalendar.from(futureDate);
XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
snapshotVersion.setTimestamp(xmlCal);
context.setSnapshotVersion(snapshotVersion);
return context;
}- Step 1 (BruksenhetService): Batch size 200 matrikkelenheter
- Step 2 (StoreService): Batch size 1000 bruksenhet IDs
// API returns: Map<MatrikkelenhetId, List<BruksenhetId>>
MatrikkelenhetIdTilBruksenhetIdsMap resultMap = bruksenhetService.findBruksenheterForMatrikkelenheter(...);
// Access via .getEntry() (not .getItem()!)
for (MatrikkelenhetIdTilBruksenhetIdsMap.Entry entry : resultMap.getEntry()) {
MatrikkelenhetId key = entry.getKey();
BruksenhetIdList value = entry.getValue();
List<BruksenhetId> ids = value.getItem();
}| Method | Bruksenheter Downloaded | Time | Status |
|---|---|---|---|
| NedlastningService (OLD) | 263,764 | ~5 min | ❌ ALL bruksenheter in kommune |
| BruksenhetService (NEW) | ~100-200 | ~10 sec | ✅ Only relevant bruksenheter |
Improvement: ~1,300x fewer objects downloaded, ~30x faster!
- pom.xml - Added BruksenhetService WSDL generation
- SoapClientConfig.java - Added BruksenhetService and StoreService beans
- BruksenhetClientWrapper.java - NEW: Two-step bruksenhet fetching
- MatrikkelenhetImportService.java - Switched from NedlastningClient to BruksenhetClient
- .github/copilot-instructions.md - Updated documentation with new approach
mvn spring-boot:run \
-Dspring-boot.run.arguments="--filter-existing --kommune=4601 --personnummer=964338531"🔍 Fetching bruksenheter for 85 matrikkelenheter using BruksenhetService + StoreService
📦 Step 1 - Batch 1/1: Getting bruksenhet IDs for 85 matrikkelenheter...
✅ Step 1 - Batch 1/1: Got 156 bruksenhet IDs (total so far: 156)
📥 Step 2: Fetching 156 full Bruksenhet objects from StoreService...
📦 Step 2 - Batch 1/1: Fetching 156 full objects...
✅ Step 2 - Batch 1/1: Fetched 156 bruksenheter
✅ Total: Fetched 156 full Bruksenhet objects for 85 matrikkelenheter
- Don't trust generic filter parameters - Dedicated API methods are more reliable
- Test with realistic data - 85 matrikkelenheter revealed the filter wasn't working
- Two-step processes are OK - BruksenhetService + StoreService is still much faster than downloading all
- API documentation isn't always complete - Had to test empirically to discover the issue
- Generated WSDL classes vary - Some use
.getItem(), some use.getEntry(), some use inner classes
- ✅ Compile and test the implementation
- ⬜ Run Phase 2 import with new bruksenhet fetching
- ⬜ Verify performance improvement
- ⬜ Consider applying same pattern to other data types (if similar issues exist)
- WSDL:
src/main/resources/wsdl/BruksenhetServiceWS.wsdl - WSDL:
src/main/resources/wsdl/StoreServiceWS.wsdl - Test results:
bygning_filter_test.log(2025-10-20)