JNDI Service Locator
Der Use Case kennt einen String-Namen und löst den Service zur Laufzeit über Context.lookup auf.
Vollständiger Legacy-Modern-Vergleich aller Java-Klassen, Tests, Maven-POMs und relevanten Ressourcen dieses Moduls. Jede Datei ist genau einmal einer fachlich passenden Vergleichsgruppe zugeordnet.
Der Use Case kennt einen String-Namen und löst den Service zur Laufzeit über Context.lookup auf.
Der Use Case erhält GreetingPort direkt über den Konstruktor.
Die Ähnlichkeit ist eine technische Orientierung auf normalisiertem Quelltext. Sie ersetzt keine fachliche Bewertung.
| Vergleichsgruppe | Legacy-Dateien | Modern-Dateien | Legacy-Zeilen | Modern-Zeilen | Ähnlichkeit |
|---|---|---|---|---|---|
| Build-Konfiguration | 1 | 1 | 34 | 39 | 40% |
| Fachlicher Port, Service, Use-Case und Test | 4 | 4 | 42 | 43 | 31% |
| JNDI-Infrastruktur und Test | 3 | 0 | 65 | 0 | 0% |
Das Pair-POM bindet die Legacy- und Modern-Submodule zusammen und gehört deshalb ebenfalls zur vollständigen Codeabdeckung.
JNDI- und moderne DI-Konfiguration wird verglichen.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| pom.xml | pom.xml | Direktvergleich Semantische Ähnlichkeit: 40% |
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>at.aydin.academy</groupId>
<artifactId>25jndiserviceresolution-pair</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>jndi-legacy</artifactId>
<packaging>jar</packaging>
<name>JNDI Legacy</name>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>at.aydin.academy</groupId>
<artifactId>25jndiserviceresolution-pair</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>service-resolution-modern</artifactId>
<packaging>jar</packaging>
<name>Service Resolution Modern</name>
<dependencies>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>Fachliche Rollen bleiben erhalten, die Auflösung wird vereinfacht.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| GreetingPort.java GreetingService.java LegacyGreetingUseCase.java LegacyGreetingUseCaseTest.java | GreetingPort.java GreetingService.java GreetingUseCase.java GreetingUseCaseTest.java | Direktvergleich Semantische Ähnlichkeit: 31% |
package at.aydin.lab.jndi.legacy;
public interface GreetingPort {
String greet(String name);
}package at.aydin.lab.jndi.legacy;
public final class GreetingService implements GreetingPort {
@Override
public String greet(String name) {
return "Hallo " + name;
}
}package at.aydin.lab.jndi.legacy;
// Design Pattern: Service Locator
// Zweck: Zeigt die versteckte Laufzeitabhängigkeit auf JNDI-Name und Naming-Infrastruktur.
public final class LegacyGreetingUseCase {
private final JndiServiceLocator locator;
public LegacyGreetingUseCase(JndiServiceLocator locator) {
this.locator = locator;
}
public String execute(String name) {
GreetingPort port = locator.resolve("service/greeting", GreetingPort.class);
return port.greet(name);
}
}package at.aydin.lab.jndi.legacy;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class LegacyGreetingUseCaseTest {
@Test
void resolvesTheDependencyByJndiName() throws Exception {
MemoryContext context = new MemoryContext();
context.rebind("service/greeting", new GreetingService());
LegacyGreetingUseCase useCase = new LegacyGreetingUseCase(new JndiServiceLocator(context));
assertEquals("Hallo Test", useCase.execute("Test"));
}
}package at.aydin.lab.jndi.modern;
// Design Pattern: Port
// Zweck: Fachcode kennt keinen JNDI-Namen und keine NamingException.
public interface GreetingPort {
String greet(String name);
}package at.aydin.lab.jndi.modern;
import org.springframework.stereotype.Service;
@Service
public class GreetingService implements GreetingPort {
public String greet(String name) {
return "Hallo " + name;
}
}package at.aydin.lab.jndi.modern;
import org.springframework.stereotype.Component;
@Component
public class GreetingUseCase {
private final GreetingPort port;
public GreetingUseCase(GreetingPort port) {
this.port = port;
}
public String execute(String name) {
return port.greet(name);
}
}package at.aydin.lab.jndi.modern;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class GreetingUseCaseTest {
@Test
void injectsExplicitPort() {
assertEquals("Hallo Test", new GreetingUseCase(new GreetingService()).execute("Test"));
}
}Service Locator und MemoryContext entfallen vollständig zugunsten direkter Injection.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| JndiServiceLocator.java MemoryContext.java JndiServiceLocatorTest.java | — | Entfällt in Modern Semantische Ähnlichkeit: 0% |
package at.aydin.lab.jndi.legacy;
import javax.naming.*;
// Design Pattern: Service Locator
// Zweck: Versteckt JNDI-Lookups, behält aber die Laufzeitabhängigkeit von String-Namen.
public final class JndiServiceLocator {
private final Context context;
public JndiServiceLocator(Context context) {
this.context = context;
}
public <T> T resolve(String name, Class<T> type) {
try {
return type.cast(context.lookup(name));
} catch (NamingException ex) {
throw new IllegalStateException(ex);
}
}
}package at.aydin.lab.jndi.legacy;
import javax.naming.*;
import java.util.*;
public final class MemoryContext extends InitialContext {
private static final Map<String, Object> VALUES = new HashMap<>();
public MemoryContext() throws NamingException {
super(true);
}
@Override
public Object lookup(String name) throws NamingException {
Object value = VALUES.get(name);
if (value == null) throw new NameNotFoundException(name);
return value;
}
@Override
public void bind(String name, Object obj) throws NamingException {
if (VALUES.putIfAbsent(name, obj) != null) throw new NameAlreadyBoundException(name);
}
@Override
public void rebind(String name, Object obj) {
VALUES.put(name, obj);
}
@Override
public void close() {
}
}package at.aydin.lab.jndi.legacy;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class JndiServiceLocatorTest {
@Test
void resolvesStringName() throws Exception {
var c = new MemoryContext();
c.rebind("service/greeting", "Hallo");
assertEquals("Hallo", new JndiServiceLocator(c).resolve("service/greeting", String.class));
}
}