001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.commons.function; 018 019/** 020 * A lifecycle-aware round-trip interface that combines both {@link BeanSupplier} (for serialization) 021 * and {@link BeanConsumer} (for parsing) on the same property or class. 022 * 023 * <p> 024 * Use this interface when the same object needs to: 025 * <ul> 026 * <li>Provide beans to a serializer (via {@link #iterator()}) 027 * <li>Receive beans from a parser (via {@link #acceptThrows(Object)}) 028 * </ul> 029 * 030 * <p> 031 * The lifecycle methods ({@link #begin()}, {@link #complete()}, {@link #onError(Exception)}) are 032 * shared across both directions. The implementation implicitly knows its direction from which data 033 * method is called first after {@link #begin()}: 034 * <ul> 035 * <li>{@link #iterator()} called first → read mode (serialization) 036 * <li>{@link #acceptThrows(Object)} called first → write mode (parsing) 037 * </ul> 038 * 039 * <p> 040 * The framework drives the lifecycle: 041 * <ol> 042 * <li>Calls {@link #begin()} before the first data operation 043 * <li>Reads via {@link #iterator()} (serializer) or writes via {@link #acceptThrows(Object)} (parser) 044 * <li>If an exception occurs, calls {@link #onError(Exception)} 045 * <li>Always calls {@link #complete()} at the end (like {@code finally}) 046 * </ol> 047 * 048 * <p> 049 * Since {@code BeanChannel} extends {@link BeanConsumer}, a {@code BeanChannel} instance passes 050 * the parser's {@code instanceof BeanConsumer} check. Since it extends {@link BeanSupplier}, it 051 * also passes the serializer's {@code instanceof BeanSupplier} check — both directions work. 052 * 053 * <h5 class='section'>Example (DB-backed round-trip channel):</h5> 054 * <p class='bjava'> 055 * <ja>@Marshalled</ja>(factory=ItemChannelFactory.<jk>class</jk>) 056 * <jk>public class</jk> ItemChannel <jk>implements</jk> BeanChannel<Item> { 057 * <jk>private</jk> Connection <jv>conn</jv>; 058 * <jk>private boolean</jk> <jv>writeMode</jv>; 059 * 060 * <ja>@Override</ja> <jk>public void</jk> begin() <jk>throws</jk> Exception { 061 * <jv>conn</jv> = <jv>ds</jv>.getConnection(); 062 * <jv>conn</jv>.setAutoCommit(<jk>false</jk>); 063 * } 064 * 065 * <jc>// Serializer calls iterator() — read mode</jc> 066 * <ja>@Override</ja> <jk>public</jk> Iterator<Item> iterator() { 067 * <jk>return new</jk> ResultSetIterator<>(...); 068 * } 069 * 070 * <jc>// Parser calls acceptThrows() — write mode</jc> 071 * <ja>@Override</ja> <jk>public void</jk> acceptThrows(Item <jv>item</jv>) <jk>throws</jk> Exception { 072 * <jv>writeMode</jv> = <jk>true</jk>; 073 * <jc>// insert item...</jc> 074 * } 075 * 076 * <ja>@Override</ja> <jk>public void</jk> onError(Exception <jv>e</jv>) <jk>throws</jk> Exception { 077 * <jk>if</jk> (<jv>writeMode</jv>) <jv>conn</jv>.rollback(); 078 * <jk>throw</jk> <jv>e</jv>; 079 * } 080 * 081 * <ja>@Override</ja> <jk>public void</jk> complete() <jk>throws</jk> Exception { 082 * <jk>if</jk> (<jv>writeMode</jv>) <jv>conn</jv>.commit(); 083 * <jv>conn</jv>.close(); 084 * } 085 * } 086 * </p> 087 * 088 * <h5 class='section'>See Also:</h5><ul> 089 * <li class='jc'>{@link BeanConsumer} - Parse-only lifecycle interface 090 * <li class='jc'>{@link BeanSupplier} - Serialize-only lifecycle interface 091 * <li class='jc'>{@link BeanFactory} - Universal factory for DI framework integration 092 * <li class='jc'>{@link ListBeanChannel} - Simple in-memory implementation 093 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a> 094 * </ul> 095 * 096 * @param <T> The type of bean read and written by this channel. 097 */ 098@SuppressWarnings({ 099 "java:S112" // throws Exception intentional - lifecycle methods may throw any checked exception 100}) 101public interface BeanChannel<T> extends BeanSupplier<T>, BeanConsumer<T> { 102 103 @Override 104 default void begin() throws Exception {} 105 106 @Override 107 default void complete() throws Exception {} 108 109 @Override 110 default void onError(Exception e) throws Exception { 111 throw e; 112 } 113}