chhh / MSFTBX

MS File ToolBox - tools for parsing some mass-spectrometry related file formats (mzML, mzXML, pep.xml, prot.xml, etc.)
Apache License 2.0
12 stars 4 forks source link

Tutorials error #4

Closed KaiLiCn closed 7 years ago

KaiLiCn commented 7 years ago

Hi:

When I tried the example on tutorials, I found something wrong as follow.

JAXBContext ctx = JAXBContext.newInstance(MsmsRunSummary.class);
  Unmarshaller unmarshaller = ctx.createUnmarshaller();

  XMLInputFactory xif = XMLInputFactory.newFactory();
  StreamSource ss = new StreamSource(is);
  XMLStreamReader xsr = xif.createXMLStreamReader(ss);

I could not find "is" in "new StreamSource(is)". Can you tell me what "is" is?

What's more, when I parsed PepXML file by

MsmsPipelineAnalysis msmsPipelineAnalysis = PepXmlParser.parse(path);

as your tutorials said. But it didn't work, the error as follow.

umich.ms.fileio.exceptions.FileParsingException: JAXB parsing of PepXML file failed (E:\Work\WenData\TCGA-A6-3807-01A-22_W_VU_20121019_A0218_4I_R_FR01.pepXML)
    at umich.ms.fileio.filetypes.pepxml.PepXmlParser.parse(PepXmlParser.java:47)
    at psmViewer.gui.NewDialog.importIdentificationFiles(NewDialog.java:778)
    at psmViewer.gui.NewDialog.access$22(NewDialog.java:769)
    at psmViewer.gui.NewDialog$7.run(NewDialog.java:529)
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
@XmlAttribute/@XmlValue need to reference a Java type that maps to text in XML.
    this problem is related to the following location:
        at protected java.lang.Object umich.ms.fileio.filetypes.pepxml.jaxb.standard.NameValueType.value
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.NameValueType
        at protected java.util.List umich.ms.fileio.filetypes.pepxml.jaxb.standard.AnalysisSummary.parameter
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.AnalysisSummary
        at protected java.util.List umich.ms.fileio.filetypes.pepxml.jaxb.standard.MsmsPipelineAnalysis.analysisSummary
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.MsmsPipelineAnalysis
    at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:102)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:438)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:286)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:139)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:117)
    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 javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:441)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
    at umich.ms.fileio.util.jaxb.JaxbUtils$Cache.<init>(JaxbUtils.java:53)
    at umich.ms.fileio.util.jaxb.JaxbUtils.getContext(JaxbUtils.java:82)
    at umich.ms.fileio.util.jaxb.JaxbUtils.unmarshall(JaxbUtils.java:160)
    at umich.ms.fileio.filetypes.pepxml.PepXmlParser.parse(PepXmlParser.java:44)
    ... 3 more

Do you know how to fix it? I will appreciate it if you can help me!

Best Regards!

Kai

chhh commented 7 years ago

@KaiLiCn Hi Kai, Can I take a look at your pepxml file? Which version of msftbx are you using? Are you using maven?

is is just an InputStream. Like a FileInputStream, for example.

chhh commented 7 years ago

@KaiLiCn Just tried it: Added the following to the POM of a new Maven project:

<dependencies>
    <dependency>
        <groupId>com.github.chhh</groupId>
        <artifactId>msftbx</artifactId>
        <version>1.3.0</version>
    </dependency>
</dependencies>
String file = "/path/to/some.pep.xml";
Path path = Paths.get(file);
MsmsPipelineAnalysis analysis = PepXmlParser.parse(path);

Worked.

chhh commented 7 years ago

Here's a complete example for the "manual style" parsing:


import umich.ms.fileio.filetypes.pepxml.PepXmlParser;
import umich.ms.fileio.filetypes.pepxml.jaxb.standard.MsmsPipelineAnalysis;
import umich.ms.fileio.filetypes.pepxml.jaxb.standard.MsmsRunSummary;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stream.StreamSource;
import java.io.FileInputStream;
import java.nio.file.Path;
import java.nio.file.Paths;

    public void testPepxmlManualReading() throws Exception {
        String file = "E:\\tmp\\q01507.pep.xml";
        Path path = Paths.get(file);

        try (FileInputStream fis = new FileInputStream(file)) {
            // we'll manually iterate over msmsRunSummaries - won't need so much memory
            // at once for processing large files.
            JAXBContext ctx = JAXBContext.newInstance(MsmsRunSummary.class);
            Unmarshaller unmarshaller = ctx.createUnmarshaller();

            XMLInputFactory xif = XMLInputFactory.newFactory();

            StreamSource ss = new StreamSource(fis);
            XMLStreamReader xsr = xif.createXMLStreamReader(ss);

            while (advanceReaderToNextRunSummary(xsr)) {
                // we've advanced to the next MsmsRunSummary in the file
                long timeLo = System.nanoTime();
                JAXBElement<MsmsRunSummary> unmarshalled = unmarshaller
                        .unmarshal(xsr, MsmsRunSummary.class);
                long timeHi = System.nanoTime();
                System.out.printf("Unmarshalling took %.4fms (%.2fs)\n",
                                  (timeHi-timeLo)/1e6, (timeHi-timeLo)/1e9);
                MsmsRunSummary runSummary = unmarshalled.getValue();
                if (runSummary.getSpectrumQuery().isEmpty()) {
                    String msg = String.format("Parsed msms_run_summary was empty for " +
                                                       "'%s', summary base_name '%s'", path.toUri().toString(), runSummary.getBaseName());
                    System.out.println(msg);
                }
            }
        } catch (JAXBException | XMLStreamException e) {
            // do something with the exception
        }

    }

    private static boolean advanceReaderToNextRunSummary(XMLStreamReader xsr)
            throws XMLStreamException {
        long timeLo = System.nanoTime();
        do {
            if (xsr.next() == XMLStreamConstants.END_DOCUMENT)
                return false;
        } while (!(xsr.isStartElement() && xsr.getLocalName().equals(TAG_RUN_SUMMARY)));

        long timeHi = System.nanoTime();
        System.out.printf("Advancing reader took: %.4fms\n", (timeHi-timeLo)/1e6d);

        return true;
    }
chhh commented 7 years ago

@KaiLiCn and here's an updated tutorial for you: http://www.batmass.org/tutorial/parsing-pep-ids/

KaiLiCn commented 7 years ago

Hi:

After checking my pepXML file, I found there are some format errors. I will try new files and thanks for your whole codes!

Best Regards!

smdb21 commented 7 years ago

Hi! I am having trouble when using this library. I think the problem is the same than the one @KaiLiCn was having. This is the error I get:

com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
@XmlAttribute/@XmlValue need to reference a Java type that maps to text in XML.
    this problem is related to the following location:
        at protected java.lang.Object umich.ms.fileio.filetypes.pepxml.jaxb.standard.NameValueType.value
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.NameValueType
        at protected java.util.List umich.ms.fileio.filetypes.pepxml.jaxb.standard.CrossLinker.crossLinkerInfo
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.CrossLinker
        at protected umich.ms.fileio.filetypes.pepxml.jaxb.standard.CrossLinker umich.ms.fileio.filetypes.pepxml.jaxb.standard.MsmsRunSummary.crossLinker
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.MsmsRunSummary

    at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:66)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:422)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:270)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:103)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:81)
    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 javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:441)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
    at org.proteored.miapeapi.xml.pepxml.PepXMLLibraryTest.readingFile(PepXMLLibraryTest.java:41)
    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:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

and this is my code. This is a piece of code taken from your example:

package org.proteored.miapeapi.xml.pepxml;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stream.StreamSource;

import org.junit.Test;
import org.springframework.core.io.ClassPathResource;

import umich.ms.fileio.filetypes.pepxml.jaxb.standard.MsmsRunSummary;

public class PepXMLLibraryTest {

    private static final String TAG_RUN_SUMMARY = "msms_run_summary";

    @Test
    public void readingFile() {
        File file;
        try {
            file = new ClassPathResource("example.pep.xml").getFile();

            Path path = Paths.get(file.toURI());

            FileInputStream fis = new FileInputStream(file);

            // we'll manually iterate over msmsRunSummaries - won't need so much
            // memory
            // at once for processing large files.
            JAXBContext ctx = JAXBContext.newInstance(MsmsRunSummary.class);
            Unmarshaller unmarshaller = ctx.createUnmarshaller();

            XMLInputFactory xif = XMLInputFactory.newInstance();

            StreamSource ss = new StreamSource(fis);
            XMLStreamReader xsr = xif.createXMLStreamReader(ss);

            while (advanceReaderToNextRunSummary(xsr)) {
                // we've advanced to the next MsmsRunSummary in the file
                long timeLo = System.nanoTime();
                JAXBElement<MsmsRunSummary> unmarshalled = unmarshaller.unmarshal(xsr, MsmsRunSummary.class);
                long timeHi = System.nanoTime();
                System.out.printf("Unmarshalling took %.4fms (%.2fs)\n", (timeHi - timeLo) / 1e6,
                        (timeHi - timeLo) / 1e9);
                MsmsRunSummary runSummary = unmarshalled.getValue();
                if (runSummary.getSpectrumQuery().isEmpty()) {
                    String msg = String.format(
                            "Parsed msms_run_summary was empty for " + "'%s', summary base_name '%s'",
                            path.toUri().toString(), runSummary.getBaseName());
                    System.out.println(msg);
                }
            }

        } catch (JAXBException | XMLStreamException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static boolean advanceReaderToNextRunSummary(XMLStreamReader xsr) throws XMLStreamException {
        long timeLo = System.nanoTime();
        do {
            if (xsr.next() == XMLStreamConstants.END_DOCUMENT)
                return false;
        } while (!(xsr.isStartElement() && xsr.getLocalName().equals(TAG_RUN_SUMMARY)));

        long timeHi = System.nanoTime();
        System.out.printf("Advancing reader took: %.4fms\n", (timeHi - timeLo) / 1e6d);

        return true;
    }
}

It is failing at this line: JAXBContext ctx = JAXBContext.newInstance(MsmsRunSummary.class);

The file I am trying to read, is attached here, which it is based on the v117 schema version: example.pep.xml.zip

I am using maven, so that I am including this dependency:

<dependency>
   <groupId>com.github.chhh</groupId>
   <artifactId>msftbx</artifactId>
   <version>1.4.0</version>
</dependency>

Could you help me please?

thanks!!

Salva.

chhh commented 7 years ago

@smdb21 Please open a new issue next time, I would not have noticed it, if not the email notification (this issue was closed already). Try a jar from this release, a lot of things have been fixed:
https://github.com/chhh/MSFTBX/releases/tag/v1.6.0-RC1

Also, everything has been greatly simplified, for smaller files you can just call:

Path path = Paths.get(<path-to-pep-xml>);
MsmsPipelineAnalysis msmsPipelineAnalysis = PepXmlParser.parse(path);

If that version works for you, I will push it to Maven Central. The original error looks strange.

For combined pepxml files (that contain multiple MsmsRunSummary tags) you can iterate over them:

FileInputStream fis = new FileInputStream(<pepxml-file>);
Iterator<MsmsRunSummary> it = PepXmlParser.parse(fis);
while (it.hasNext()) {
    ...
}
smdb21 commented 7 years ago

I am sorry to have put this here. I though that the error was the same than the described before.

Anyway, I tried the jar you provided and I got the same exception when trying both ways to use the PepXmlParser.

Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
@XmlAttribute/@XmlValue need to reference a Java type that maps to text in XML.
    this problem is related to the following location:
        at protected java.lang.Object umich.ms.fileio.filetypes.pepxml.jaxb.standard.NameValueType.value
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.NameValueType
        at protected java.util.List umich.ms.fileio.filetypes.pepxml.jaxb.standard.CrossLinker.crossLinkerInfo
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.CrossLinker
        at protected umich.ms.fileio.filetypes.pepxml.jaxb.standard.CrossLinker umich.ms.fileio.filetypes.pepxml.jaxb.standard.MsmsRunSummary.crossLinker
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.MsmsRunSummary

The full error stack trace is:

umich.ms.fileio.exceptions.FileParsingException: Could not create JAXBContext/Unmarshaller for msms_run_summary
    at umich.ms.fileio.filetypes.pepxml.PepXmlStreamIterator.create(PepXmlStreamIterator.java:65)
    at umich.ms.fileio.filetypes.pepxml.PepXmlParser.parse(PepXmlParser.java:66)
    at org.proteored.miapeapi.xml.pepxml.PepXMLLibraryTest.readingFile(PepXMLLibraryTest.java:38)
    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:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
@XmlAttribute/@XmlValue need to reference a Java type that maps to text in XML.
    this problem is related to the following location:
        at protected java.lang.Object umich.ms.fileio.filetypes.pepxml.jaxb.standard.NameValueType.value
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.NameValueType
        at protected java.util.List umich.ms.fileio.filetypes.pepxml.jaxb.standard.CrossLinker.crossLinkerInfo
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.CrossLinker
        at protected umich.ms.fileio.filetypes.pepxml.jaxb.standard.CrossLinker umich.ms.fileio.filetypes.pepxml.jaxb.standard.MsmsRunSummary.crossLinker
        at umich.ms.fileio.filetypes.pepxml.jaxb.standard.MsmsRunSummary

    at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:66)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:422)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:270)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:103)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:81)
    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 javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:441)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
    at umich.ms.fileio.filetypes.pepxml.PepXmlStreamIterator.create(PepXmlStreamIterator.java:62)
    ... 25 more
chhh commented 7 years ago

I have put together another attempt to fix:
https://github.com/chhh/MSFTBX/releases/tag/v1.6.0-RC1 It's the same location, but updated JARs.

The problem is I can't reproduce the issue. But I understand what the exception says, though I don't know why, it all works fine for me.

smdb21 commented 7 years ago

It works now! Let me know if you push it to the maven central. Thank you very much for your quick response!

Salva.

chhh commented 7 years ago

@smdb21 Could you please still report what the following commands output:

smdb21 commented 7 years ago

javac -version: javac 1.8.0_121

java -version

java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.141-b15, mixed mode)
chhh commented 7 years ago

@smdb21 pushed 1.6.0 to Maven Central. It should be showing up in searches in 2-6 hours.