Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build-the-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up JDK 21
- name: Set up JDK 25
uses: actions/setup-java@v1
with:
java-version: 21
java-version: 25
- name: Cache Maven packages
uses: actions/cache@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-release-to-maven-repository.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Setup build environment
uses: actions/setup-java@v1
with:
java-version: 21
java-version: 25
server-id: central
server-username: ${{ secrets.NEXUS_USERNAME }}
server-password: ${{ secrets.NEXUS_PASSWORD }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Setup build environment
uses: actions/setup-java@v1
with:
java-version: 21
java-version: 25
- name: Create the release artifact
run: mvn package -DskipTests -Pci
- name: Create pre-release
Expand Down Expand Up @@ -52,7 +52,7 @@ jobs:
- name: Setup build environment
uses: actions/setup-java@v1
with:
java-version: 21
java-version: 25
- name: Create the release artifact
run: mvn package -DskipTests -D"assembly.name=GA" -Pci
- name: Create the Windows installer
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-snapshot-to-maven-repository.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Setup build environment
uses: actions/setup-java@v1
with:
java-version: 21
java-version: 25
server-id: central
server-username: ${{ secrets.NEXUS_USERNAME }}
server-password: ${{ secrets.NEXUS_PASSWORD }}
Expand Down
2 changes: 1 addition & 1 deletion NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ STEPS TO UPGRADE.
v3.0 to ensure your database is in the right state to migrate from
V2 to v3.
2. If you are not running from a Docker container, you will need to
install Java 21.
install Java 25.
3. Before you install this release, you MUST drop the batch tables with the
following query:
* DROP TABLE BATCH_STEP_EXECUTION_CONTEXT;
Expand Down
2 changes: 1 addition & 1 deletion QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ComiXed makes heavy use of databases to manage the information for a
comic book library. As such, it requires one that provides a stable,
durable environment.

ComiXed ships with support for two database environments:
ComiXed ships with support for three database environments:
* [MySQL](https://www.mysql.com/) v8.1 or later
* [MariaDB](https://mariadb.org/) v10.11 or later.
* [PosgreSQL](https://www.postgresql.org/) v16.0 or later
Expand Down
23 changes: 23 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,26 @@ DROP SEQUENCE BATCH_JOB_SEQ IF EXISTS;
```

After this, you can then run ComiXed 2.0.

## v3.x -> v4.x

If you are running a version prior to v3.x, then you **must** first upgrade
to v3.x. After installing v3.x and running it, you should run the server
once to perform some necessary database changes. Then you can perform the
recommended upgrade steps.

Next you will need to run the following SQL. To do this, start up ComiXed with the
database console enabled using the **-C** commandline option:

```sql
DROP TABLE BATCH_STEP_EXECUTION_CONTEXT IF EXISTS;
DROP TABLE BATCH_JOB_EXECUTION_CONTEXT IF EXISTS;
DROP TABLE BATCH_STEP_EXECUTION IF EXISTS;
DROP TABLE BATCH_JOB_EXECUTION_PARAMS IF EXISTS;
DROP TABLE BATCH_JOB_EXECUTION IF EXISTS;
DROP TABLE BATCH_JOB_INSTANCE IF EXISTS;

DROP SEQUENCE BATCH_STEP_EXECUTION_SEQ IF EXISTS;
DROP SEQUENCE BATCH_JOB_EXECUTION_SEQ IF EXISTS;
DROP SEQUENCE BATCH_JOB_SEQ IF EXISTS;
```
4 changes: 0 additions & 4 deletions comixed-adaptors/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@
<artifactId>imageio-webp</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.xml.JacksonXmlHttpMessageConverter;

/**
* <code>AdaptorConfiguration</code> provides beans for the adaptors package.
Expand All @@ -41,4 +42,10 @@ public Tika tika() {
public Metadata metadata() {
return new Metadata();
}

/** replaces the default mapper used before the migration */
@Bean
public JacksonXmlHttpMessageConverter xmlHttpMessageConverter() {
return new JacksonXmlHttpMessageConverter();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@
import static org.apache.commons.lang3.StringUtils.trim;
import static org.apache.commons.lang3.StringUtils.truncate;

import com.fasterxml.jackson.databind.DeserializationFeature;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
Expand All @@ -38,8 +36,10 @@
import org.comixedproject.model.comicpages.ComicPage;
import org.comixedproject.model.metadata.ComicInfo;
import org.comixedproject.model.metadata.PageInfo;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.http.converter.xml.JacksonXmlHttpMessageConverter;
import org.springframework.util.StringUtils;
import tools.jackson.core.exc.StreamReadException;
import tools.jackson.databind.DeserializationFeature;

/**
* <code>ComicInfoXmlFilenameContentAdaptor</code> provides an implementation of {@link
Expand All @@ -52,13 +52,15 @@ public class ComicInfoXmlFilenameContentAdaptor implements FilenameContentAdapto
@Getter private ArchiveEntryType archiveEntryType = ArchiveEntryType.FILE;

private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private MappingJackson2XmlHttpMessageConverter xmlConverter;
private final JacksonXmlHttpMessageConverter xmlConverter;

public ComicInfoXmlFilenameContentAdaptor() {
this.xmlConverter = new MappingJackson2XmlHttpMessageConverter();
this.xmlConverter = new JacksonXmlHttpMessageConverter();
this.xmlConverter
.getObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
.getMapper()
.rebuild()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.build();
}

@Override
Expand All @@ -69,7 +71,7 @@ public void loadContent(final ComicBook comicBook, final String filename, final
try {
comicInfo =
this.xmlConverter
.getObjectMapper()
.getMapper()
.readValue(new ByteArrayInputStream(content), ComicInfo.class);
log.trace("Setting comic metadata");
comicBook.getComicDetail().setPublisher(trim(comicInfo.getPublisher()));
Expand Down Expand Up @@ -163,7 +165,7 @@ public void loadContent(final ComicBook comicBook, final String filename, final
}
}
}
} catch (IOException | ParseException error) {
} catch (StreamReadException | ParseException error) {
throw new ContentAdaptorException("Failed to load ComicInfo.xml", error);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@

package org.comixedproject.adaptors.content;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
Expand All @@ -32,22 +30,30 @@
import org.comixedproject.model.metadata.PageType;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.converter.xml.JacksonXmlHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import tools.jackson.core.JacksonException;
import tools.jackson.databind.DeserializationFeature;

@Component
@Log4j2
public class ComicMetadataWriter implements InitializingBean {
@Autowired MappingJackson2XmlHttpMessageConverter xmlConverter;

@Autowired
@Qualifier("xmlHttpMessageConverter")
private JacksonXmlHttpMessageConverter xmlConverter;

private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

@Override
public void afterPropertiesSet() throws Exception {
this.xmlConverter
.getObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
.getMapper()
.rebuild()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.build();
}

/**
Expand Down Expand Up @@ -182,8 +188,8 @@ public byte[] createContent(ComicBook comicBook) throws ContentAdaptorException
});
try {
log.trace("Generating ComicInfo.xml data");
return this.xmlConverter.getObjectMapper().writeValueAsBytes(comicInfo);
} catch (JsonProcessingException error) {
return this.xmlConverter.getMapper().writeValueAsBytes(comicInfo);
} catch (JacksonException error) {
throw new ContentAdaptorException("Failed to write ComicInfo.xml data", error);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.*;
import org.comixedproject.model.comicbooks.*;
import org.comixedproject.model.comicpages.ComicPage;
Expand All @@ -21,7 +20,10 @@
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.http.converter.xml.JacksonXmlHttpMessageConverter;
import tools.jackson.core.JacksonException;
import tools.jackson.databind.DeserializationFeature;
import tools.jackson.dataformat.xml.XmlMapper;

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
Expand All @@ -32,8 +34,9 @@ class ComicMetadataWriterTest {
private static final Date TEST_LAST_SCRAPED_DATE = new Date();

@InjectMocks private ComicMetadataWriter writer;
@Mock private ObjectMapper objectMapper;
@Mock MappingJackson2XmlHttpMessageConverter xmlConverter;
@Mock JacksonXmlHttpMessageConverter xmlConverter;
@Mock XmlMapper xmlMapper;
@Mock XmlMapper.Builder xmlMapperBuilder;
@Mock private ComicDetail comicDetail;
@Mock private MetadataSource metadataSource;
@Mock private ComicMetadataSource comicMetadataSource;
Expand All @@ -46,10 +49,14 @@ class ComicMetadataWriterTest {
private List<ComicPage> comicPages = new ArrayList<>();

@BeforeEach
void setUp() throws JsonProcessingException {
Mockito.when(objectMapper.writeValueAsBytes(metadataArgumentCaptor.capture()))
void setUp() {
Mockito.when(xmlConverter.getMapper()).thenReturn(xmlMapper);
when(xmlMapper.rebuild()).thenReturn(xmlMapperBuilder);
when(xmlMapperBuilder.configure(any(DeserializationFeature.class), Mockito.anyBoolean()))
.thenReturn(xmlMapperBuilder);
when(xmlMapperBuilder.build()).thenReturn(xmlMapper);
Mockito.when(xmlMapper.writeValueAsBytes(metadataArgumentCaptor.capture()))
.thenReturn(contentByte);
Mockito.when(xmlConverter.getObjectMapper()).thenReturn(objectMapper);
Mockito.when(comicDetail.getCoverDate()).thenReturn(TEST_COVER_DATE);
for (int index = 0; index < ComicTagType.values().length; index++) {
tags.add(new ComicTag(comicDetail, ComicTagType.values()[index], "Tag Value " + index));
Expand All @@ -76,8 +83,9 @@ void setUp() throws JsonProcessingException {
void afterPropertiesSet() throws Exception {
writer.afterPropertiesSet();

Mockito.verify(objectMapper, Mockito.times(1))
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
verify(xmlMapper).rebuild();
verify(xmlMapperBuilder).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
verify(xmlMapperBuilder).build();
}

@Test
Expand All @@ -97,9 +105,9 @@ void createContent_metadataContent() throws ContentAdaptorException {
}

@Test
void createContent_objectWriterException() throws IOException {
Mockito.when(objectMapper.writeValueAsBytes(metadataArgumentCaptor.capture()))
.thenThrow(JsonProcessingException.class);
void createContent_objectWriterException() {
Mockito.when(xmlMapper.writeValueAsBytes(metadataArgumentCaptor.capture()))
.thenThrow(JacksonException.class);

assertThrows(ContentAdaptorException.class, () -> writer.createContent(comicBook));
}
Expand Down
8 changes: 4 additions & 4 deletions comixed-app/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
<name>comixed-app</name>
<url>http://www.comixedproject.org</url>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
Expand Down Expand Up @@ -68,6 +64,10 @@
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
4 changes: 4 additions & 0 deletions comixed-app/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ spring.datasource.url=jdbc:h2:file:~/.comixed/comixed
spring.datasource.username=sa
spring.datasource.password=

# Jackson config
spring.jackson.deserialization.fail-on-unknown-properties=false
spring.jackson.date-format=yyyy-MM-dd

# Batch processing
# Set this value to the number of parallel batch processes desired:
# n - allow up to n threads
Expand Down
4 changes: 0 additions & 4 deletions comixed-auth/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
<name>comixed-auth</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void doFilter(
ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest currentRequest = (HttpServletRequest) servletRequest;
var wrappedRequest = new ContentCachingRequestWrapper(currentRequest);
var wrappedRequest = new ContentCachingRequestWrapper(currentRequest, 0);

chain.doFilter(wrappedRequest, servletResponse);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,9 @@ public SecurityFilterChain restSecurityFilterChain(final HttpSecurity http) thro
*
* @param http the security builder
* @return the filter chain
* @throws Exception if an error occurs
*/
@Bean
public SecurityFilterChain opdsSecurityFilterChain(final HttpSecurity http) throws Exception {
public SecurityFilterChain opdsSecurityFilterChain(final HttpSecurity http) {
http.securityMatcher("/opds/**", "/reader/v1/**")
.authorizeHttpRequests(authz -> authz.anyRequest().hasRole("READER"))
.httpBasic(Customizer.withDefaults());
Expand All @@ -100,7 +99,7 @@ public SecurityFilterChain opdsSecurityFilterChain(final HttpSecurity http) thro
}

@Bean
public SecurityFilterChain runtimeSecurityFilterChain(final HttpSecurity http) throws Exception {
public SecurityFilterChain runtimeSecurityFilterChain(final HttpSecurity http) {
http.securityMatcher("/actuator/**")
.cors(Customizer.withDefaults())
.csrf(AbstractHttpConfigurer::disable)
Expand Down
Loading
Loading