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 producer for use as a serializer source, providing beans lazily one at a time. 021 * 022 * <p> 023 * Extends {@link Iterable} so that {@code ClassMeta}'s existing {@code ITERABLE} category picks it 024 * up automatically — no new type category is needed in the framework. 025 * 026 * <p> 027 * The serializer drives the full lifecycle: 028 * <ol> 029 * <li>Calls {@link #begin()} before iteration starts 030 * <li>Iterates elements via {@link #iterator()}, serializing each 031 * <li>If an exception occurs during iteration, calls {@link #onError(Exception)} 032 * <li>Always calls {@link #complete()} after iteration (like {@code finally}) — whether 033 * serialization succeeded or failed. Use this for resource cleanup (close cursors, connections, etc.) 034 * </ol> 035 * 036 * <p> 037 * For round-trip support (same property used for both serialization and parsing), use 038 * {@link BeanChannel} instead, which extends both {@link BeanSupplier} and {@link BeanConsumer}. 039 * 040 * <p> 041 * If a {@link BeanSupplier} is encountered during parsing (not serialization), the parser will 042 * throw an {@link IllegalArgumentException} with a message recommending {@link BeanConsumer} or 043 * {@link BeanChannel}. 044 * 045 * <h5 class='section'>Example (DB-backed supplier via JDBC cursor):</h5> 046 * <p class='bjava'> 047 * <ja>@Marshalled</ja>(factory=ItemSupplierFactory.<jk>class</jk>) 048 * <jk>public class</jk> ItemSupplier <jk>implements</jk> BeanSupplier<Item> { 049 * <jk>private</jk> Connection <jv>conn</jv>; 050 * <jk>private</jk> ResultSet <jv>rs</jv>; 051 * 052 * <ja>@Override</ja> <jk>public void</jk> begin() <jk>throws</jk> Exception { 053 * <jv>conn</jv> = <jv>ds</jv>.getConnection(); 054 * <jv>rs</jv> = <jv>conn</jv>.prepareStatement(<js>"SELECT * FROM items"</js>).executeQuery(); 055 * } 056 * 057 * <ja>@Override</ja> <jk>public</jk> Iterator<Item> iterator() { 058 * <jk>return new</jk> ResultSetIterator<>(<jv>rs</jv>, Item::<jv>fromRow</jv>); 059 * } 060 * 061 * <ja>@Override</ja> <jk>public void</jk> onError(Exception <jv>e</jv>) <jk>throws</jk> Exception { 062 * <jv>rs</jv>.close(); <jk>throw</jk> <jv>e</jv>; 063 * } 064 * 065 * <ja>@Override</ja> <jk>public void</jk> complete() <jk>throws</jk> Exception { 066 * <jv>rs</jv>.close(); <jv>conn</jv>.close(); 067 * } 068 * } 069 * </p> 070 * 071 * <h5 class='section'>See Also:</h5><ul> 072 * <li class='jc'>{@link BeanConsumer} - Parse-only lifecycle interface 073 * <li class='jc'>{@link BeanChannel} - Round-trip lifecycle interface (extends both) 074 * <li class='jc'>{@link BeanFactory} - Universal factory for DI framework integration 075 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a> 076 * </ul> 077 * 078 * @param <T> The type of bean provided by this supplier. 079 */ 080@SuppressWarnings({ 081 "java:S112" // throws Exception intentional - lifecycle methods may throw any checked exception 082}) 083public interface BeanSupplier<T> extends Iterable<T> { 084 085 /** 086 * Called before iteration starts. 087 * 088 * <p> 089 * Use this to open database connections, execute queries, or perform other setup. 090 * 091 * @throws Exception If setup fails. 092 */ 093 default void begin() throws Exception {} 094 095 /** 096 * Always called after iteration ends (like {@code finally}). 097 * 098 * <p> 099 * Use this to close database cursors, connections, or release other resources. 100 * This method is called whether serialization succeeded or {@link #onError(Exception)} rethrew. 101 * 102 * @throws Exception If cleanup fails. 103 */ 104 default void complete() throws Exception {} 105 106 /** 107 * Called when an exception occurs during iteration. 108 * 109 * <p> 110 * The default implementation rethrows the exception, stopping serialization immediately. 111 * Note that {@link #complete()} is always called afterward regardless. 112 * 113 * @param e The exception that occurred during iteration. 114 * @throws Exception If the error cannot be recovered from. Rethrow {@code e} to stop serialization. 115 */ 116 default void onError(Exception e) throws Exception { 117 throw e; 118 } 119}