I have a service that gets an URL from the user input, extracts the body content of this URL, apply CSS, and finally returns the result as a stream.
The tricky part is that I have different implementations depending on the URL, if the URL is not recognized, then a "default" implementation is used. To do so, I used a BeanFactory to choose the correct implementation on Runtime.
@Service
@Qualifier("defaultHtmlToHtmlService")
public class DefaultHtmlToHtmlImpl implements HtmlToHtmlService {
@Override
public InputStream htmlToHtml(String url) throws IOException {
Document document = Jsoup.connect(url).get();
Element content = document.body();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(content.outerHtml().getBytes());
outputStream.close();
return new ByteArrayInputStream(outputStream.toByteArray());
}
}
@Component
public class BeanFactory {
private final HtmlToHtmlService defaultHtmlToHtmlService;
private final HtmlToHtmlService impl1;
private final HtmlToHtmlService impl2;
@Autowired
public BeanFactory(@Qualifier("defaultHtmlToHtmlImpl") HtmlToHtmlService defaultHtmlToHtmlService,
@Qualifier("impl1") HtmlToHtmlService impl1,
@Qualifier("impl2") HtmlToHtmlService impl2) {
this.defaultHtmlToHtmlService = defaultHtmlToHtmlService;
this.impl1 = impl1;
this.impl2 = impl2;
}
public HtmlToHtmlService getHtmlToHtmlImpl(String url) {
if (url.contains("some pattern")) {
return impl1;
} else if (url.contains("some other pattern")) {
return impl2;
} else {
return defaultHtmlToHtmlService;
}
}
This is working just fine. However, my issue is that I don't want my BeanFactory to share any information with the rest, but I do not know how to decouple it. Basically, I want to remove the @Qualifier
annotation, and not to have to manually enter the new URL patterns in the Bean Factory in the future when I will get more implementations.
I saw that maybe @PostConstruct
annotation or using static blocks could be the solution, but I am really not sure how to apply it in this case.