Skip to content

Commit

Permalink
#6 Implemented Failure Analyzer for Situations, where a Service Endpo…
Browse files Browse the repository at this point in the history
…int Interface (SEI) could´nt be found. Also refactored the WebServiceAutoDetector module architecture that now separates the Scanning and the working with the specific WebService-Classes. That also results in the possiblility to use Mocks instead of preimplemented WebServiceAutoDetector Testable class, which never felt right.
  • Loading branch information
jonashackt committed Nov 16, 2016
1 parent 199a317 commit 4f03fa3
Show file tree
Hide file tree
Showing 13 changed files with 254 additions and 197 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

import de.codecentric.cxf.common.BootStarterCxfException;
import de.codecentric.cxf.diagnostics.SeiImplClassNotFoundException;
import de.codecentric.cxf.diagnostics.SeiNotFoundException;
import de.codecentric.cxf.diagnostics.WebServiceClientNotFoundException;
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
import io.github.lukehutch.fastclasspathscanner.scanner.ScanResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -13,92 +12,52 @@
import javax.xml.ws.WebServiceClient;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;


public class WebServiceAutoDetector {

private static final Logger LOG = LoggerFactory.getLogger(WebServiceAutoDetector.class);
protected static final String NO_CLASS_FOUND = "No class found";
private final WebServiceScanner webServiceScanner;

public static final Class<WebService> SEI_ANNOTATION = WebService.class;
public static final Class<WebServiceClient> WEB_SERVICE_CLIENT_ANNOTATION = WebServiceClient.class;

public WebServiceAutoDetector(WebServiceScanner webServiceScanner) {
this.webServiceScanner = webServiceScanner;
}

@SuppressWarnings("unchecked")
public <T> T searchAndInstantiateSeiImplementation(Class seiName) throws BootStarterCxfException {
Class<T> implementingClass = null;
try {
implementingClass = scanForClassWhichImplementsAndPickFirst(seiName);
implementingClass = webServiceScanner.scanForClassWhichImplementsAndPickFirst(seiName);
LOG.info("Found SEI implementing class: '{}'", implementingClass.getName());
} catch (BootStarterCxfException exception) {
SeiImplClassNotFoundException seiNotFound = new SeiImplClassNotFoundException("No SEI implementing class found");
seiNotFound.setNotFoundClassName(seiName.getName());
throw seiNotFound;
throw SeiImplClassNotFoundException.build().setNotFoundClassName(seiName.getName());
}
return instantiateFromClass(implementingClass);
}

public Class searchServiceEndpointInterface() throws BootStarterCxfException {
Class sei = scanForClassWithAnnotationAndIsAnInterface(WebService.class);
LOG.info("Found Service Endpoint Interface (SEI): '{}'", sei.getName());
return sei;
try{
Class sei = webServiceScanner.scanForClassWithAnnotationAndIsAnInterface(SEI_ANNOTATION);
LOG.info("Found Service Endpoint Interface (SEI): '{}'", sei.getName());
return sei;
} catch (BootStarterCxfException exception) {
throw new SeiNotFoundException();
}
}

@SuppressWarnings("unchecked")
public Service searchAndInstantiateWebServiceClient() throws BootStarterCxfException {
try{
Class<Service> webServiceClientClass = scanForClassWithAnnotationAndPickTheFirstOneFound(WebServiceClient.class);
Class<Service> webServiceClientClass = webServiceScanner.scanForClassWithAnnotationAndPickTheFirstOneFound(WEB_SERVICE_CLIENT_ANNOTATION);
LOG.info("Found WebServiceClient class: '{}'", webServiceClientClass.getName());
return instantiateFromClass(webServiceClientClass);
} catch (BootStarterCxfException exception) {
throw new WebServiceClientNotFoundException(
"There was no class found, that´s annotated with javax.xml.ws.WebServiceClient and implements javax.xml.ws.Service");
}
}

protected <T> Class scanForClassWithAnnotationAndPickTheFirstOneFound(Class<T> annotationName) throws BootStarterCxfException {
return classForName(scanForClassNamesWithAnnotation(annotationName).get(0));
}

protected <T> Class scanForClassWithAnnotationAndIsAnInterface(Class<T> annotationName) throws BootStarterCxfException {
List<String> namesOfClassesWithAnnotation = scanForClassNamesWithAnnotation(annotationName);

if(namesOfClassesWithAnnotation.size() > 1) {
return justPickTheClassThatIsAnInterface(namesOfClassesWithAnnotation);
} else {
return classForName(namesOfClassesWithAnnotation.get(0));
}
}

protected <T> List<String> scanForClassNamesWithAnnotation(Class<T> annotationName) throws BootStarterCxfException {
List<String> namesOfClassesWithAnnotation = initScannerAndScan().getNamesOfClassesWithAnnotation(annotationName);

if(namesOfClassesWithAnnotation.isEmpty()) {
throw new BootStarterCxfException(NO_CLASS_FOUND);
throw new WebServiceClientNotFoundException();
}
return namesOfClassesWithAnnotation;
}

protected Class justPickTheClassThatIsAnInterface(List<String> namesOfClassesWithAnnotation) throws BootStarterCxfException {
for (String className : namesOfClassesWithAnnotation) {
if (isInterface(className)) {
return classForName(className);
}
}
throw new BootStarterCxfException(NO_CLASS_FOUND);
}

protected boolean isInterface(String className) throws BootStarterCxfException {
return classForName(className).isInterface();
}

protected <T> Class scanForClassWhichImplementsAndPickFirst(Class<T> interfaceName) throws BootStarterCxfException {
List<String> namesOfClassesImplementing = initScannerAndScan().getNamesOfClassesImplementing(interfaceName);
if(namesOfClassesImplementing.isEmpty()) {
throw new BootStarterCxfException(NO_CLASS_FOUND);
}
return classForName(namesOfClassesImplementing.get(0));
}

private ScanResult initScannerAndScan() {
return new FastClasspathScanner().scan();
}

private <T> T instantiateFromClass(Class<T> clazz) throws BootStarterCxfException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package de.codecentric.cxf.autodetection;

import de.codecentric.cxf.common.BootStarterCxfException;
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
import io.github.lukehutch.fastclasspathscanner.scanner.ScanResult;

import java.util.List;

public class WebServiceScanner {

protected static final String NO_CLASS_FOUND = "No class found";

protected <T> Class scanForClassWhichImplementsAndPickFirst(Class<T> interfaceName) throws BootStarterCxfException {
List<String> namesOfClassesImplementing = initScannerAndScan().getNamesOfClassesImplementing(interfaceName);
if (namesOfClassesImplementing.isEmpty()) {
throw new BootStarterCxfException(WebServiceAutoDetector.NO_CLASS_FOUND);
}
return classForName(namesOfClassesImplementing.get(0));
}

protected <T> Class scanForClassWithAnnotationAndPickTheFirstOneFound(Class<T> annotationName) throws BootStarterCxfException {
return classForName(scanForClassNamesWithAnnotation(annotationName).get(0));
}

protected <T> List<String> scanForClassNamesWithAnnotation(Class<T> annotationName) throws BootStarterCxfException {
List<String> namesOfClassesWithAnnotation = initScannerAndScan().getNamesOfClassesWithAnnotation(annotationName);

if(namesOfClassesWithAnnotation.isEmpty()) {
throw new BootStarterCxfException(NO_CLASS_FOUND);
}
return namesOfClassesWithAnnotation;
}

protected <T> Class scanForClassWithAnnotationAndIsAnInterface(Class<T> annotationName) throws BootStarterCxfException {
List<String> namesOfClassesWithAnnotation = scanForClassNamesWithAnnotation(annotationName);

if(namesOfClassesWithAnnotation.size() > 1) {
return justPickTheClassThatIsAnInterface(namesOfClassesWithAnnotation);
} else {
return classForName(namesOfClassesWithAnnotation.get(0));
}
}

protected Class justPickTheClassThatIsAnInterface(List<String> namesOfClassesWithAnnotation) throws BootStarterCxfException {
for (String className : namesOfClassesWithAnnotation) {
if (isInterface(className)) {
return classForName(className);
}
}
throw new BootStarterCxfException(NO_CLASS_FOUND);
}

protected boolean isInterface(String className) throws BootStarterCxfException {
return classForName(className).isInterface();
}

private ScanResult initScannerAndScan() {
return new FastClasspathScanner().scan();
}


protected Class<?> classForName(String className) throws BootStarterCxfException {
try {
return Class.forName(className);
} catch (ClassNotFoundException exception) {
throw new BootStarterCxfException(NO_CLASS_FOUND, exception);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import javax.xml.ws.Service;

import de.codecentric.cxf.autodetection.WebServiceAutoDetector;
import de.codecentric.cxf.autodetection.WebServiceScanner;
import de.codecentric.cxf.common.BootStarterCxfException;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
Expand Down Expand Up @@ -48,7 +49,7 @@ public class CxfAutoConfiguration {

private String serviceUrlEnding = "";

private WebServiceAutoDetector webServiceAutoDetector = new WebServiceAutoDetector();;
private WebServiceAutoDetector webServiceAutoDetector = new WebServiceAutoDetector(new WebServiceScanner());;

@PostConstruct
public void setUp() throws BootStarterCxfException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@
*/
public class SeiImplClassNotFoundException extends BootStarterCxfException {

public SeiImplClassNotFoundException(String message) {
super(message);
protected static final String MESSAGE = "The Service Endpoint Interface (SEI) implementing class could´nt be found";

public SeiImplClassNotFoundException() {
super(MESSAGE);
}

public static SeiImplClassNotFoundException build() {
return new SeiImplClassNotFoundException();
}

private String notFoundClassName;
Expand All @@ -19,7 +25,8 @@ public String getNotFoundClassName() {
return notFoundClassName;
}

public void setNotFoundClassName(String notFoundClassName) {
public SeiImplClassNotFoundException setNotFoundClassName(String notFoundClassName) {
this.notFoundClassName = notFoundClassName;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class SeiImplMissingFailureAnalyzer extends AbstractFailureAnalyzer<SeiIm

@Override
protected FailureAnalysis analyze(Throwable rootFailure, SeiImplClassNotFoundException cause) {
return new FailureAnalysis("There was no SEI implementing class found.",
return new FailureAnalysis(SeiImplClassNotFoundException.MESSAGE,
String.format("Build a Class that implements your Service Endpoint Interface (SEI): '%s' and try again!", cause.getNotFoundClassName()), cause);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package de.codecentric.cxf.diagnostics;

import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;

/**
* FailureAnalyzer to show custom Failure Message, if the Service Endpoint Interface (SEI) is missing
* (which is mandatory for autodetection and instantiation of the CXF endpoint(s))
*
* @author jonashackt
*/
public class SeiMissingFailureAnalyzer extends AbstractFailureAnalyzer<SeiNotFoundException>{

@Override
protected FailureAnalysis analyze(Throwable rootFailure, SeiNotFoundException cause) {
return new FailureAnalysis(SeiNotFoundException.MESSAGE,
"Use the cxf-spring-boot-starter-maven-plugin (https://github.com/codecentric/cxf-spring-boot-starter-maven-plugin) " +
"to generate the needed class files from your WSDL & XSDs", cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package de.codecentric.cxf.diagnostics;

import de.codecentric.cxf.common.BootStarterCxfException;

/**
* Thrown when the Service Endpoint Interface (SEI) itself isn´t found.
*
* @author jonashackt
*/
public class SeiNotFoundException extends BootStarterCxfException {

protected static final String MESSAGE = "The Service Endpoint Interface (SEI) could´nt be found - an interface that´s annotated with javax.jws.WebService";

public SeiNotFoundException() {
super(MESSAGE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
*/
public class WebServiceClientNotFoundException extends BootStarterCxfException {

public WebServiceClientNotFoundException(String message) {
super(message);
protected static final String MESSAGE = "There was no class found, that´s annotated with javax.xml.ws.WebServiceClient and implements javax.xml.ws.Service";

public WebServiceClientNotFoundException() {
super(MESSAGE);
}
}
Loading

0 comments on commit 4f03fa3

Please sign in to comment.