Background: We have a method in a spring boot application which builds a word doc using aspose and converts it to PDF and returns.
But before converting to pdf, aspose has to load some Arial fonts from resources folder.
This was not happening because of the way we were trying to access the fonts. This was causing alignment issues.
We worked on it, and fixed the way we were loading fonts. This resolved the issue.
Current Issue:
Now we want to create a JUnit test case which will check if the font is loaded.
I wrote the below test case, it gives a success in the end but throws an error as well.
Error: After this error, it still prints the loaded Fonts and exits with a success.
The error is thrown at below code in getAllLoadedFonts method mentioned below.
fontSource.getAvailableFonts()
java.util.ServiceConfigurationError: javax.print.PrintServiceLookup: Provider sun.print.PrintServiceLookupProvider not a subtype
at java.util.ServiceLoader.fail(ServiceLoader.java:239)
at java.util.ServiceLoader.access$300(ServiceLoader.java:185)
at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:376)
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
at javax.print.PrintServiceLookup$1.run(PrintServiceLookup.java:347)
at java.security.AccessController.doPrivileged(Native Method)
at javax.print.PrintServiceLookup.getAllLookupServices(PrintServiceLookup.java:338)
at javax.print.PrintServiceLookup.lookupDefaultPrintService(PrintServiceLookup.java:180)
at com.aspose.words.WindowsNativeCall.<clinit>(Unknown Source)
at com.aspose.words.internal.zz9H.<clinit>(Unknown Source)
at com.aspose.words.internal.zzBI.zzU(Unknown Source)
at com.aspose.words.internal.zzBJ.zzQX(Unknown Source)
at com.aspose.words.internal.zzR9.zzZ(Unknown Source)
at com.aspose.words.FontSourceBase.getAvailableFonts(Unknown Source)
at mypackage.getAllLoadedFonts(WordBuilderServiceTest.java:214)
at mypackage.testIfAllFontsAreLoadedProperly(WordBuilderServiceTest.java:207)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:149)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:141)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.withContextClassLoader(DelegatingPowerMockRunner.java:132)
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:141)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:121)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Below is my test case and associated methods:
private WordBuilderService wordBuilderService;
@Before
public void setUp() {
initMocks(this);
wordBuilderService = spy(new WordBuilderService(//some other variables))
}
@Test
public void testIfAllFontsAreLoadedProperly () throws DtException {
FontSettings fontSettings = new FontSettings();
wordBuilderService.addFontsFromClasspathViaStream(fontSettings);
assertTrue(getAllLoadedFonts(fontSettings).contains("Arial"));
}
private String getAllLoadedFonts(FontSettings fontSettings) {
FontSourceBase[] fontSources = fontSettings.getFontsSources();
StringBuilder fontNames= new StringBuilder();
for (FontSourceBase fontSource : fontSources) {
try {
ArrayList<PhysicalFontInfo> availableFonts = fontSource.getAvailableFonts();
for (PhysicalFontInfo font : availableFonts) {
fontNames.append( font.getFullFontName());
fontNames.append(", ");
}
} catch (Exception e) {
System.err.println("Error retrieving available fonts: " + e.getMessage());
}
}
log.info(fontNames.toString());
return fontNames.toString();
}
addFontsFromClasspathViaStream Method in WordBuilderService:
public void addFontsFromClasspathViaStream(FontSettings fontSettings) throws DtException {
List<InputStream> fontStreams = new ArrayList<>();
List<String> fontFileNames = Arrays.asList("ARIAL.TTF","ARIALBD.TTF","ARIALBI.TTF","ARIALI.TTF","ARIALN.TTF","ARIALNB.TTF","ARIALNBI.TTF"
,"ARIALNI.TTF","ARIBLK.TTF");
try {
for (String fontFilePath : fontFileNames) {
log.info("{}: trying to get this file via Stream",fontFilePath);
InputStream fontStream = new ClassPathResource("fonts/"+fontFilePath).getInputStream();
if (fontStream != null) {
log.info("{}: got this file via Stream",fontFilePath);
byte[] fontData = IOUtils.toByteArray(fontStream);
MemoryFontSource memoryFontSource = new MemoryFontSource(fontData);
FontSourceBase[] existingSources = fontSettings.getFontsSources();
FontSourceBase[] newSources = new FontSourceBase[existingSources.length + 1];
System.arraycopy(existingSources, 0, newSources, 0, existingSources.length);
newSources[newSources.length - 1] = memoryFontSource;
fontSettings.setFontsSources(newSources);
fontStreams.add(fontStream);
} else {
log.error("Font stream is null for: " + fontFilePath);
}
}
} catch(IOException e){
log.error("Error Loading the Fonts, pdf will be misaligned.");
} finally {
// Close all streams
for (InputStream fontStream : fontStreams) {
try{
if (fontStream != null) {
fontStream.close();
}
} catch (IOException e) {
//Nothing needed
}
}
}
}
And we are using aspose 18.11
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>18.11</version>
<classifier>jdk16</classifier>
</dependency>
Any help or suggestions regarding this is much appreciated.
I tried checking various online forums, tried asking ChatGPT, tried catching the exception and just logging, but still it throws entire error.