From b95d5b20d86c44f15c9b15dd328cc81f0614ea01 Mon Sep 17 00:00:00 2001 From: Daniel Kec Date: Sat, 6 Jun 2020 22:34:14 +0200 Subject: [PATCH 1/2] Lazy list for even lazier MediaType acceptedTypes parsing Signed-off-by: Daniel Kec Checkstyle fix Signed-off-by: Daniel Kec --- .../main/java/io/helidon/common/LazyList.java | 46 ++++ .../java/io/helidon/common/LazyListImpl.java | 248 ++++++++++++++++++ .../java/io/helidon/common/LazyListTest.java | 155 +++++++++++ .../common/MessageBodyWriterContext.java | 25 +- .../helidon/webserver/HashRequestHeaders.java | 20 +- .../io/helidon/webserver/RequestRouting.java | 5 +- .../java/io/helidon/webserver/Response.java | 3 +- .../io/helidon/webserver/ResponseTest.java | 3 +- 8 files changed, 479 insertions(+), 26 deletions(-) create mode 100644 common/common/src/main/java/io/helidon/common/LazyList.java create mode 100644 common/common/src/main/java/io/helidon/common/LazyListImpl.java create mode 100644 common/common/src/test/java/io/helidon/common/LazyListTest.java diff --git a/common/common/src/main/java/io/helidon/common/LazyList.java b/common/common/src/main/java/io/helidon/common/LazyList.java new file mode 100644 index 00000000000..cb9a3b48d13 --- /dev/null +++ b/common/common/src/main/java/io/helidon/common/LazyList.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.common; + +import java.util.List; +import java.util.function.Supplier; + +/** + * Wrapper for list of {@link io.helidon.common.LazyValue}s while keeping laziness. + * + * @param type of the provided object + */ +public interface LazyList extends List { + + /** + * Add another lazy item to the list. + * + * @param supplier to be invoke only when necessary + */ + void add(Supplier supplier); + + /** + * Create wrapper from provided list of {@link io.helidon.common.LazyValue}s. + * + * @param lazyValues to be wrapped seamlessly while keeping laziness + * @param type of the provided object + * @return List invoking underlined {@link io.helidon.common.LazyValue}s only when raw value is needed. + */ + static LazyList create(List> lazyValues) { + return new LazyListImpl<>(lazyValues); + } +} diff --git a/common/common/src/main/java/io/helidon/common/LazyListImpl.java b/common/common/src/main/java/io/helidon/common/LazyListImpl.java new file mode 100644 index 00000000000..2a047b61a2b --- /dev/null +++ b/common/common/src/main/java/io/helidon/common/LazyListImpl.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.common; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Objects; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +class LazyListImpl implements LazyList { + + private final List> lazyValues = new ArrayList<>(); + private List allLoaded; + + LazyListImpl(List> lazyValues) { + this.lazyValues.addAll(lazyValues); + } + + @Override + public void add(final Supplier supplier) { + lazyValues.add(LazyValue.create(supplier)); + } + + private List loadAll() { + if (allLoaded == null) { + allLoaded = lazyValues.stream().map(LazyValue::get).collect(Collectors.toList()); + } + return allLoaded; + } + + @Override + public int size() { + return lazyValues.size(); + } + + @Override + public boolean isEmpty() { + return lazyValues.isEmpty(); + } + + @Override + public boolean contains(final Object o) { + return lazyValues.stream() + .map(LazyValue::get) + .anyMatch(tLazyValue -> Objects.equals(o, tLazyValue)); + } + + @Override + public Iterator iterator() { + Iterator> lazyValueIterator = lazyValues.iterator(); + return new Iterator() { + @Override + public boolean hasNext() { + return lazyValueIterator.hasNext(); + } + + @Override + public T next() { + return lazyValueIterator.next().get(); + } + }; + } + + @Override + public Object[] toArray() { + return loadAll().toArray(); + } + + @Override + public T1[] toArray(final T1[] a) { + return loadAll().toArray(a); + } + + @Override + public boolean add(final T t) { + return lazyValues.add(LazyValue.create(t)); + } + + @Override + public boolean remove(final Object o) { + return lazyValues.removeIf(lv -> Objects.equals(o, lv.get())); + } + + @Override + public boolean containsAll(final Collection c) { + return loadAll().containsAll(c); + } + + @Override + public boolean addAll(final Collection c) { + c.forEach(v -> lazyValues.add(LazyValue.create(v))); + return !c.isEmpty(); + } + + @Override + public boolean addAll(final int index, final Collection c) { + c.forEach(this::add); + return !c.isEmpty(); + } + + @Override + public boolean removeAll(final Collection c) { + return loadAll().removeAll(c); + } + + @Override + public boolean retainAll(final Collection c) { + return loadAll().retainAll(c); + } + + @Override + public void clear() { + lazyValues.clear(); + if (allLoaded != null) { + allLoaded.clear(); + } + } + + @Override + public T get(final int index) { + return lazyValues.get(index).get(); + } + + @Override + public T set(final int index, final T element) { + return lazyValues.set(index, LazyValue.create(element)).get(); + } + + @Override + public void add(final int index, final T element) { + lazyValues.add(index, LazyValue.create(element)); + } + + @Override + public T remove(final int index) { + return lazyValues.remove(index).get(); + } + + @Override + public int indexOf(final Object o) { + for (int i = 0; i < lazyValues.size(); i++) { + LazyValue lv = lazyValues.get(i); + if (Objects.equals(o, lv.get())) { + return i; + } + } + return -1; + } + + @Override + public int lastIndexOf(final Object o) { + int index = -1; + for (int i = 0; i < lazyValues.size(); i++) { + LazyValue lv = lazyValues.get(i); + if (Objects.equals(o, lv.get())) { + index = i; + } + } + return index; + } + + @Override + public ListIterator listIterator() { + return new LazyListIterator<>(lazyValues.listIterator()); + } + + @Override + public ListIterator listIterator(final int index) { + return new LazyListIterator<>(lazyValues.listIterator(index)); + } + + @Override + public List subList(final int fromIndex, final int toIndex) { + return new LazyListImpl<>(lazyValues.subList(fromIndex, toIndex)); + } + + private static class LazyListIterator implements ListIterator { + + private final ListIterator> innerIterator; + + LazyListIterator(ListIterator> innerIterator) { + this.innerIterator = innerIterator; + } + + @Override + public boolean hasNext() { + return this.innerIterator.hasNext(); + } + + @Override + public T next() { + return this.innerIterator.next().get(); + } + + @Override + public boolean hasPrevious() { + return this.innerIterator.hasPrevious(); + } + + @Override + public T previous() { + return this.innerIterator.previous().get(); + } + + @Override + public int nextIndex() { + return this.innerIterator.nextIndex(); + } + + @Override + public int previousIndex() { + return this.innerIterator.previousIndex(); + } + + @Override + public void remove() { + this.innerIterator.remove(); + } + + @Override + public void set(final T t) { + this.innerIterator.set(LazyValue.create(t)); + } + + @Override + public void add(final T t) { + this.innerIterator.add(LazyValue.create(t)); + } + } +} diff --git a/common/common/src/test/java/io/helidon/common/LazyListTest.java b/common/common/src/test/java/io/helidon/common/LazyListTest.java new file mode 100644 index 00000000000..2d66c53ba2f --- /dev/null +++ b/common/common/src/test/java/io/helidon/common/LazyListTest.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2020 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.common; + +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; + +public class LazyListTest { + @Test + void getSizeAdd() { + String text = "Helidon"; + List calledCounters = + IntStream.rangeClosed(1, 4) + .boxed() + .map(integer -> new AtomicInteger()) + .collect(Collectors.toList()); + + List> lazyValues = IntStream.rangeClosed(0, 3) + .mapToObj(i -> LazyValue.create(() -> { + calledCounters.get(i).incrementAndGet(); + return text + i; + })).collect(Collectors.toList()); + + List lazyList = LazyList.create(lazyValues.subList(0, 3)); + + assertCounters(calledCounters, 0, 0, 0, 0); + + assertThat(lazyList.size(), is(3)); + assertThat(lazyList.get(0), is(text + "0")); + + assertCounters(calledCounters, 1, 0, 0, 0); + + assertThat(lazyList.get(1), is(text + "1")); + + assertCounters(calledCounters, 1, 1, 0, 0); + lazyList.add("notLazy"); + assertCounters(calledCounters, 1, 1, 0, 0); + + assertThat(lazyList.get(2), is(text + "2")); + assertCounters(calledCounters, 1, 1, 1, 0); + assertThat(lazyList.size(), is(4)); + assertCounters(calledCounters, 1, 1, 1, 0); + + + ((LazyList) lazyList).add(lazyValues.get(3)); + assertCounters(calledCounters, 1, 1, 1, 0); + assertThat(lazyList.size(), is(5)); + assertCounters(calledCounters, 1, 1, 1, 0); + assertThat(lazyList.get(3), is("notLazy")); + assertCounters(calledCounters, 1, 1, 1, 0); + + assertThat(lazyList.get(4), is(text + "3")); + assertCounters(calledCounters, 1, 1, 1, 1); + + } + + @Test + void iterator() { + String text = "Helidon"; + List calledCounters = + IntStream.rangeClosed(0, 3) + .mapToObj(i -> new AtomicInteger()) + .collect(Collectors.toList()); + + List> lazyValues = IntStream.rangeClosed(0, 3) + .mapToObj(i -> LazyValue.create(() -> { + calledCounters.get(i).incrementAndGet(); + return text + i; + })).collect(Collectors.toList()); + + List lazyList = LazyList.create(lazyValues); + + Iterator lazyIterator = lazyList.iterator(); + + assertCounters(calledCounters, 0, 0, 0, 0); + assertThat(lazyIterator.hasNext(), is(equalTo(true))); + assertCounters(calledCounters, 0, 0, 0, 0); + + assertThat(lazyIterator.next(), is(equalTo(text + "0"))); + assertCounters(calledCounters, 1, 0, 0, 0); + assertThat(lazyIterator.hasNext(), is(equalTo(true))); + assertCounters(calledCounters, 1, 0, 0, 0); + + assertThat(lazyIterator.next(), is(equalTo(text + "1"))); + assertCounters(calledCounters, 1, 1, 0, 0); + assertThat(lazyIterator.hasNext(), is(equalTo(true))); + assertCounters(calledCounters, 1, 1, 0, 0); + + assertThat(lazyIterator.next(), is(equalTo(text + "2"))); + assertCounters(calledCounters, 1, 1, 1, 0); + assertThat(lazyIterator.hasNext(), is(equalTo(true))); + assertCounters(calledCounters, 1, 1, 1, 0); + + assertThat(lazyIterator.next(), is(equalTo(text + "3"))); + assertCounters(calledCounters, 1, 1, 1, 1); + assertThat(lazyIterator.hasNext(), is(equalTo(false))); + assertCounters(calledCounters, 1, 1, 1, 1); + } + + @Test + void forEach() { + String text = "Helidon"; + List calledCounters = + IntStream.rangeClosed(0, 3) + .mapToObj(i -> new AtomicInteger()) + .collect(Collectors.toList()); + + List> lazyValues = IntStream.rangeClosed(0, 3) + .mapToObj(i -> LazyValue.create(() -> { + calledCounters.get(i).incrementAndGet(); + return text + i; + })).collect(Collectors.toList()); + + List lazyList = LazyList.create(lazyValues); + + assertCounters(calledCounters, 0, 0, 0, 0); + + int i = 0; + Integer[] shiftArray = {0, 0, 0, 0}; + for (String val : lazyList) { + shiftArray[i] = 1; + assertCounters(calledCounters, shiftArray); + assertThat(val, is(equalTo(text + i))); + i++; + } + } + + private void assertCounters(List calledCounters, Integer... expected) { + assertThat(calledCounters.stream().map(AtomicInteger::get).collect(Collectors.toList()), contains(expected)); + } +} diff --git a/media/common/src/main/java/io/helidon/media/common/MessageBodyWriterContext.java b/media/common/src/main/java/io/helidon/media/common/MessageBodyWriterContext.java index 43c578c2b20..73afac7adc8 100644 --- a/media/common/src/main/java/io/helidon/media/common/MessageBodyWriterContext.java +++ b/media/common/src/main/java/io/helidon/media/common/MessageBodyWriterContext.java @@ -27,7 +27,6 @@ import java.util.function.Predicate; import io.helidon.common.GenericType; -import io.helidon.common.LazyValue; import io.helidon.common.http.DataChunk; import io.helidon.common.http.Http; import io.helidon.common.http.MediaType; @@ -53,7 +52,7 @@ public final class MessageBodyWriterContext extends MessageBodyContext implement private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; private final Parameters headers; - private final LazyValue> acceptedTypes; + private final List acceptedTypes; private final MessageBodyOperators> writers; private final MessageBodyOperators> swriters; private boolean contentTypeCached; @@ -65,7 +64,7 @@ public final class MessageBodyWriterContext extends MessageBodyContext implement * Private to enforce the use of the static factory methods. */ private MessageBodyWriterContext(MessageBodyWriterContext parent, EventListener eventListener, Parameters headers, - LazyValue> acceptedTypes) { + List acceptedTypes) { super(parent, eventListener); Objects.requireNonNull(headers, "headers cannot be null!"); @@ -73,7 +72,7 @@ private MessageBodyWriterContext(MessageBodyWriterContext parent, EventListener if (acceptedTypes != null) { this.acceptedTypes = acceptedTypes; } else { - this.acceptedTypes = LazyValue.create(List.of()); + this.acceptedTypes = List.of(); } if (parent != null) { this.writers = new MessageBodyOperators<>(parent.writers); @@ -94,7 +93,7 @@ private MessageBodyWriterContext(Parameters headers) { this.headers = headers; this.writers = new MessageBodyOperators<>(); this.swriters = new MessageBodyOperators<>(); - this.acceptedTypes = LazyValue.create(List.of()); + this.acceptedTypes = List.of(); } /** @@ -105,7 +104,7 @@ private MessageBodyWriterContext() { this.headers = ReadOnlyParameters.empty(); this.writers = new MessageBodyOperators<>(); this.swriters = new MessageBodyOperators<>(); - this.acceptedTypes = LazyValue.create(List.of()); + this.acceptedTypes = List.of(); this.contentTypeCache = Optional.empty(); this.contentTypeCached = true; this.charsetCache = DEFAULT_CHARSET; @@ -118,7 +117,7 @@ private MessageBodyWriterContext(MessageBodyWriterContext writerContext, Paramet this.headers = headers; this.writers = new MessageBodyOperators<>(writerContext.writers); this.swriters = new MessageBodyOperators<>(writerContext.swriters); - this.acceptedTypes = writerContext.acceptedTypes; + this.acceptedTypes = List.copyOf(writerContext.acceptedTypes); this.contentTypeCache = writerContext.contentTypeCache; this.contentTypeCached = writerContext.contentTypeCached; this.charsetCache = writerContext.charsetCache; @@ -137,7 +136,7 @@ private MessageBodyWriterContext(MessageBodyWriterContext writerContext, Paramet * @return MessageBodyWriterContext */ public static MessageBodyWriterContext create(MediaContext mediaContext, EventListener eventListener, Parameters headers, - LazyValue> acceptedTypes) { + List acceptedTypes) { if (mediaContext == null) { return new MessageBodyWriterContext(null, eventListener, headers, acceptedTypes); @@ -156,7 +155,7 @@ public static MessageBodyWriterContext create(MediaContext mediaContext, EventLi * @return MessageBodyWriterContext */ public static MessageBodyWriterContext create(MessageBodyWriterContext parent, EventListener eventListener, - Parameters headers, LazyValue> acceptedTypes) { + Parameters headers, List acceptedTypes) { return new MessageBodyWriterContext(parent, eventListener, headers, acceptedTypes); } @@ -416,7 +415,7 @@ public Optional contentType() { * @return List never {@code null} */ public List acceptedTypes() { - return acceptedTypes.get(); + return acceptedTypes; } /** @@ -468,10 +467,10 @@ public MediaType findAccepted(Predicate predicate, MediaType defaultT Objects.requireNonNull(defaultType, "defaultType cannot be null"); MediaType contentType = contentType().orElse(null); if (contentType == null) { - if (acceptedTypes.get().isEmpty()) { + if (acceptedTypes.isEmpty()) { return defaultType; } else { - for (final MediaType acceptedType : acceptedTypes.get()) { + for (final MediaType acceptedType : acceptedTypes) { if (predicate.test(acceptedType)) { if (acceptedType.isWildcardType() || acceptedType.isWildcardSubtype()) { return defaultType; @@ -497,7 +496,7 @@ public MediaType findAccepted(Predicate predicate, MediaType defaultT */ public MediaType findAccepted(MediaType mediaType) throws IllegalStateException { Objects.requireNonNull(mediaType, "mediaType cannot be null"); - for (MediaType acceptedType : acceptedTypes.get()) { + for (MediaType acceptedType : acceptedTypes) { if (mediaType.equals(acceptedType)) { return acceptedType; } diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/HashRequestHeaders.java b/webserver/webserver/src/main/java/io/helidon/webserver/HashRequestHeaders.java index 50080eb8923..fe20d53cb57 100644 --- a/webserver/webserver/src/main/java/io/helidon/webserver/HashRequestHeaders.java +++ b/webserver/webserver/src/main/java/io/helidon/webserver/HashRequestHeaders.java @@ -26,6 +26,8 @@ import java.util.OptionalLong; import java.util.stream.Collectors; +import io.helidon.common.LazyList; +import io.helidon.common.LazyValue; import io.helidon.common.http.HashParameters; import io.helidon.common.http.Http; import io.helidon.common.http.MediaType; @@ -113,12 +115,18 @@ public List acceptedTypes() { List result = this.acceptedtypesCache; if (result == null) { List acceptValues = all(Http.Header.ACCEPT); - result = acceptValues.size() == 1 && HUC_ACCEPT_DEFAULT.equals(acceptValues.get(0)) - ? HUC_ACCEPT_DEFAULT_TYPES : acceptValues.stream() - .flatMap(h -> Utils.tokenize(',', "\"", false, h).stream()) - .map(String::trim) - .map(MediaType::parse) - .collect(Collectors.toList()); + + if (acceptValues.size() == 1 && HUC_ACCEPT_DEFAULT.equals(acceptValues.get(0))) { + result = HUC_ACCEPT_DEFAULT_TYPES; + + } else { + result = LazyList.create(acceptValues.stream() + .flatMap(h -> Utils.tokenize(',', "\"", false, h).stream()) + .map(String::trim) + .map(s -> LazyValue.create(() -> MediaType.parse(s))) + .collect(Collectors.toList())); + } + result = Collections.unmodifiableList(result); this.acceptedtypesCache = result; } diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/RequestRouting.java b/webserver/webserver/src/main/java/io/helidon/webserver/RequestRouting.java index cbab2e82b75..7cbc481d35a 100644 --- a/webserver/webserver/src/main/java/io/helidon/webserver/RequestRouting.java +++ b/webserver/webserver/src/main/java/io/helidon/webserver/RequestRouting.java @@ -28,7 +28,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import io.helidon.common.LazyValue; import io.helidon.common.context.Contexts; import io.helidon.common.http.AlreadyCompletedException; import io.helidon.common.http.Http; @@ -73,7 +72,7 @@ public void route(BareRequest bareRequest, BareResponse bareResponse) { RoutedResponse response = new RoutedResponse( webServer, bareResponse, - LazyValue.create(requestHeaders::acceptedTypes)); + requestHeaders.acceptedTypes()); // Jersey needs the raw path (not decoded) so we get that too String path = canonicalize(bareRequest.uri().normalize().getPath()); @@ -442,7 +441,7 @@ public ServerRequest.Path path() { private static class RoutedResponse extends Response { - RoutedResponse(WebServer webServer, BareResponse bareResponse, LazyValue> acceptedTypes) { + RoutedResponse(WebServer webServer, BareResponse bareResponse, List acceptedTypes) { super(webServer, bareResponse, acceptedTypes); } diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/Response.java b/webserver/webserver/src/main/java/io/helidon/webserver/Response.java index 52ce45fb5bb..3af3e80d096 100644 --- a/webserver/webserver/src/main/java/io/helidon/webserver/Response.java +++ b/webserver/webserver/src/main/java/io/helidon/webserver/Response.java @@ -25,7 +25,6 @@ import java.util.function.Predicate; import io.helidon.common.GenericType; -import io.helidon.common.LazyValue; import io.helidon.common.http.DataChunk; import io.helidon.common.http.Http; import io.helidon.common.http.MediaType; @@ -66,7 +65,7 @@ abstract class Response implements ServerResponse { * @param webServer a web server. * @param bareResponse an implementation of the response SPI. */ - Response(WebServer webServer, BareResponse bareResponse, LazyValue> acceptedTypes) { + Response(WebServer webServer, BareResponse bareResponse, List acceptedTypes) { this.webServer = webServer; this.bareResponse = bareResponse; this.headers = new HashResponseHeaders(bareResponse); diff --git a/webserver/webserver/src/test/java/io/helidon/webserver/ResponseTest.java b/webserver/webserver/src/test/java/io/helidon/webserver/ResponseTest.java index 68916a7525c..737af5e2954 100644 --- a/webserver/webserver/src/test/java/io/helidon/webserver/ResponseTest.java +++ b/webserver/webserver/src/test/java/io/helidon/webserver/ResponseTest.java @@ -30,7 +30,6 @@ import java.util.function.Function; import io.helidon.common.GenericType; -import io.helidon.common.LazyValue; import io.helidon.common.http.DataChunk; import io.helidon.common.http.Http; import io.helidon.common.http.MediaType; @@ -259,7 +258,7 @@ public void filters() throws Exception { static class ResponseImpl extends Response { public ResponseImpl(BareResponse bareResponse) { - super(mock(WebServer.class), bareResponse, LazyValue.create(List.of())); + super(mock(WebServer.class), bareResponse, List.of()); } @Override From db4490405c6f6d8fd300d6cfa73fee407ebd289e Mon Sep 17 00:00:00 2001 From: Daniel Kec Date: Fri, 12 Jun 2020 11:55:14 +0200 Subject: [PATCH 2/2] Get rid of laziness breaker Signed-off-by: Daniel Kec --- .../java/io/helidon/media/common/MessageBodyWriterContext.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/common/src/main/java/io/helidon/media/common/MessageBodyWriterContext.java b/media/common/src/main/java/io/helidon/media/common/MessageBodyWriterContext.java index 73afac7adc8..14558efb406 100644 --- a/media/common/src/main/java/io/helidon/media/common/MessageBodyWriterContext.java +++ b/media/common/src/main/java/io/helidon/media/common/MessageBodyWriterContext.java @@ -117,7 +117,7 @@ private MessageBodyWriterContext(MessageBodyWriterContext writerContext, Paramet this.headers = headers; this.writers = new MessageBodyOperators<>(writerContext.writers); this.swriters = new MessageBodyOperators<>(writerContext.swriters); - this.acceptedTypes = List.copyOf(writerContext.acceptedTypes); + this.acceptedTypes = writerContext.acceptedTypes; this.contentTypeCache = writerContext.contentTypeCache; this.contentTypeCached = writerContext.contentTypeCached; this.charsetCache = writerContext.charsetCache;