001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.beans.factory; 018 019import java.io.PrintStream; 020import java.io.PrintWriter; 021import java.util.ArrayList; 022import java.util.List; 023 024import org.springframework.beans.FatalBeanException; 025import org.springframework.core.NestedRuntimeException; 026import org.springframework.lang.Nullable; 027 028/** 029 * Exception thrown when a BeanFactory encounters an error when 030 * attempting to create a bean from a bean definition. 031 * 032 * @author Juergen Hoeller 033 */ 034@SuppressWarnings("serial") 035public class BeanCreationException extends FatalBeanException { 036 037 @Nullable 038 private final String beanName; 039 040 @Nullable 041 private final String resourceDescription; 042 043 @Nullable 044 private List<Throwable> relatedCauses; 045 046 047 /** 048 * Create a new BeanCreationException. 049 * @param msg the detail message 050 */ 051 public BeanCreationException(String msg) { 052 super(msg); 053 this.beanName = null; 054 this.resourceDescription = null; 055 } 056 057 /** 058 * Create a new BeanCreationException. 059 * @param msg the detail message 060 * @param cause the root cause 061 */ 062 public BeanCreationException(String msg, Throwable cause) { 063 super(msg, cause); 064 this.beanName = null; 065 this.resourceDescription = null; 066 } 067 068 /** 069 * Create a new BeanCreationException. 070 * @param beanName the name of the bean requested 071 * @param msg the detail message 072 */ 073 public BeanCreationException(String beanName, String msg) { 074 super("Error creating bean with name '" + beanName + "': " + msg); 075 this.beanName = beanName; 076 this.resourceDescription = null; 077 } 078 079 /** 080 * Create a new BeanCreationException. 081 * @param beanName the name of the bean requested 082 * @param msg the detail message 083 * @param cause the root cause 084 */ 085 public BeanCreationException(String beanName, String msg, Throwable cause) { 086 this(beanName, msg); 087 initCause(cause); 088 } 089 090 /** 091 * Create a new BeanCreationException. 092 * @param resourceDescription description of the resource 093 * that the bean definition came from 094 * @param beanName the name of the bean requested 095 * @param msg the detail message 096 */ 097 public BeanCreationException(@Nullable String resourceDescription, @Nullable String beanName, String msg) { 098 super("Error creating bean with name '" + beanName + "'" + 099 (resourceDescription != null ? " defined in " + resourceDescription : "") + ": " + msg); 100 this.resourceDescription = resourceDescription; 101 this.beanName = beanName; 102 this.relatedCauses = null; 103 } 104 105 /** 106 * Create a new BeanCreationException. 107 * @param resourceDescription description of the resource 108 * that the bean definition came from 109 * @param beanName the name of the bean requested 110 * @param msg the detail message 111 * @param cause the root cause 112 */ 113 public BeanCreationException(@Nullable String resourceDescription, String beanName, String msg, Throwable cause) { 114 this(resourceDescription, beanName, msg); 115 initCause(cause); 116 } 117 118 119 /** 120 * Return the description of the resource that the bean 121 * definition came from, if any. 122 */ 123 @Nullable 124 public String getResourceDescription() { 125 return this.resourceDescription; 126 } 127 128 /** 129 * Return the name of the bean requested, if any. 130 */ 131 @Nullable 132 public String getBeanName() { 133 return this.beanName; 134 } 135 136 /** 137 * Add a related cause to this bean creation exception, 138 * not being a direct cause of the failure but having occurred 139 * earlier in the creation of the same bean instance. 140 * @param ex the related cause to add 141 */ 142 public void addRelatedCause(Throwable ex) { 143 if (this.relatedCauses == null) { 144 this.relatedCauses = new ArrayList<>(); 145 } 146 this.relatedCauses.add(ex); 147 } 148 149 /** 150 * Return the related causes, if any. 151 * @return the array of related causes, or {@code null} if none 152 */ 153 @Nullable 154 public Throwable[] getRelatedCauses() { 155 if (this.relatedCauses == null) { 156 return null; 157 } 158 return this.relatedCauses.toArray(new Throwable[0]); 159 } 160 161 162 @Override 163 public String toString() { 164 StringBuilder sb = new StringBuilder(super.toString()); 165 if (this.relatedCauses != null) { 166 for (Throwable relatedCause : this.relatedCauses) { 167 sb.append("\nRelated cause: "); 168 sb.append(relatedCause); 169 } 170 } 171 return sb.toString(); 172 } 173 174 @Override 175 public void printStackTrace(PrintStream ps) { 176 synchronized (ps) { 177 super.printStackTrace(ps); 178 if (this.relatedCauses != null) { 179 for (Throwable relatedCause : this.relatedCauses) { 180 ps.println("Related cause:"); 181 relatedCause.printStackTrace(ps); 182 } 183 } 184 } 185 } 186 187 @Override 188 public void printStackTrace(PrintWriter pw) { 189 synchronized (pw) { 190 super.printStackTrace(pw); 191 if (this.relatedCauses != null) { 192 for (Throwable relatedCause : this.relatedCauses) { 193 pw.println("Related cause:"); 194 relatedCause.printStackTrace(pw); 195 } 196 } 197 } 198 } 199 200 @Override 201 public boolean contains(@Nullable Class<?> exClass) { 202 if (super.contains(exClass)) { 203 return true; 204 } 205 if (this.relatedCauses != null) { 206 for (Throwable relatedCause : this.relatedCauses) { 207 if (relatedCause instanceof NestedRuntimeException && 208 ((NestedRuntimeException) relatedCause).contains(exClass)) { 209 return true; 210 } 211 } 212 } 213 return false; 214 } 215 216}