-
Notifications
You must be signed in to change notification settings - Fork 8.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fecd9d4
commit 498075a
Showing
2 changed files
with
274 additions
and
0 deletions.
There are no files selected for viewing
197 changes: 197 additions & 0 deletions
197
compatible/src/main/java/io/seata/integration/tx/api/interceptor/ActionContextUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You 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.seata.integration.tx.api.interceptor; | ||
|
||
import io.seata.rm.tcc.api.BusinessActionContextParameter; | ||
import org.apache.seata.common.util.CollectionUtils; | ||
import org.apache.seata.common.util.StringUtils; | ||
import org.apache.seata.rm.tcc.api.BusinessActionContext; | ||
import org.apache.seata.rm.tcc.api.ParamType; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import javax.annotation.Nonnull; | ||
import javax.annotation.Nullable; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
/** | ||
* Extracting TCC Context from Method | ||
*/ | ||
public final class ActionContextUtil { | ||
|
||
private ActionContextUtil() { | ||
} | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(ActionContextUtil.class); | ||
|
||
/** | ||
* Extracting context data from parameters | ||
* | ||
* @param targetParam the target param | ||
* @return map the context | ||
*/ | ||
public static Map<String, Object> fetchContextFromObject(@Nonnull Object targetParam) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.fetchContextFromObject(targetParam); | ||
} | ||
|
||
/** | ||
* load param by the config of annotation, and then put into the action context | ||
* | ||
* @param paramType the param type, 'param' or 'field' | ||
* @param paramName the param name | ||
* @param paramValue the param value | ||
* @param annotation the annotation on the param or field | ||
* @param actionContext the action context | ||
*/ | ||
public static void loadParamByAnnotationAndPutToContext(@Nonnull final ParamType paramType, @Nonnull String paramName, Object paramValue, | ||
@Nonnull final BusinessActionContextParameter annotation, @Nonnull final Map<String, Object> actionContext) { | ||
if (paramValue == null) { | ||
return; | ||
} | ||
|
||
// If {@code index >= 0}, get by index from the list param or field | ||
int index = annotation.index(); | ||
if (index >= 0) { | ||
paramValue = getByIndex(paramType, paramName, paramValue, index); | ||
if (paramValue == null) { | ||
return; | ||
} | ||
} | ||
|
||
// if {@code isParamInProperty == true}, fetch context from paramValue | ||
if (annotation.isParamInProperty()) { | ||
Map<String, Object> paramContext = fetchContextFromObject(paramValue); | ||
if (CollectionUtils.isNotEmpty(paramContext)) { | ||
actionContext.putAll(paramContext); | ||
} | ||
} else { | ||
// get param name from the annotation | ||
String paramNameFromAnnotation = getParamNameFromAnnotation(annotation); | ||
if (StringUtils.isNotBlank(paramNameFromAnnotation)) { | ||
paramName = paramNameFromAnnotation; | ||
} | ||
putActionContextWithoutHandle(actionContext, paramName, paramValue); | ||
} | ||
} | ||
|
||
@Nullable | ||
private static Object getByIndex(@Nonnull ParamType paramType, @Nonnull String paramName, @Nonnull Object paramValue, int index) { | ||
if (paramValue instanceof List) { | ||
@SuppressWarnings("unchecked") | ||
List<Object> list = (List<Object>) paramValue; | ||
if (list.isEmpty()) { | ||
return null; | ||
} | ||
if (list.size() <= index) { | ||
if (LOGGER.isDebugEnabled()) { | ||
LOGGER.debug("The index '{}' is out of bounds for the list {} named '{}'," + | ||
" whose size is '{}', so pass this {}", index, paramType.getCode(), paramName, list.size(), paramType.getCode()); | ||
} | ||
return null; | ||
} | ||
paramValue = list.get(index); | ||
} else { | ||
LOGGER.warn("the {} named '{}' is not a `List`, so the 'index' field of '@{}' cannot be used on it", | ||
paramType.getCode(), paramName, BusinessActionContextParameter.class.getSimpleName()); | ||
} | ||
|
||
return paramValue; | ||
} | ||
|
||
public static String getParamNameFromAnnotation(@Nonnull BusinessActionContextParameter annotation) { | ||
String paramName = annotation.paramName(); | ||
if (StringUtils.isBlank(paramName)) { | ||
paramName = annotation.value(); | ||
} | ||
return paramName; | ||
} | ||
|
||
/** | ||
* put the action context after handle | ||
* | ||
* @param actionContext the action context | ||
* @param key the actionContext's key | ||
* @param value the actionContext's value | ||
* @return the action context is changed | ||
*/ | ||
public static boolean putActionContext(Map<String, Object> actionContext, String key, Object value) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.putActionContext(actionContext, key, value); | ||
} | ||
|
||
/** | ||
* put the action context after handle | ||
* | ||
* @param actionContext the action context | ||
* @param actionContextMap the actionContextMap | ||
* @return the action context is changed | ||
*/ | ||
public static boolean putActionContext(Map<String, Object> actionContext, @Nonnull Map<String, Object> actionContextMap) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.putActionContext(actionContext, actionContextMap); | ||
} | ||
|
||
/** | ||
* put the action context without handle | ||
* | ||
* @param actionContext the action context | ||
* @param key the actionContext's key | ||
* @param value the actionContext's value | ||
* @return the action context is changed | ||
*/ | ||
public static boolean putActionContextWithoutHandle(@Nonnull final Map<String, Object> actionContext, String key, Object value) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.putActionContextWithoutHandle(actionContext, key, value); | ||
} | ||
|
||
/** | ||
* put the action context without handle | ||
* | ||
* @param actionContext the action context | ||
* @param actionContextMap the actionContextMap | ||
* @return the action context is changed | ||
*/ | ||
public static boolean putActionContextWithoutHandle(Map<String, Object> actionContext, @Nonnull Map<String, Object> actionContextMap) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.putActionContextWithoutHandle(actionContext, actionContextMap); | ||
} | ||
|
||
/** | ||
* Handle the action context. | ||
* It is convenient to convert type in phase 2. | ||
* | ||
* @param actionContext the action context | ||
* @return the action context or JSON string | ||
* @see #convertActionContext(String, Object, Class) | ||
* @see BusinessActionContext#getActionContext(String, Class) | ||
*/ | ||
public static Object handleActionContext(@Nonnull Object actionContext) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.handleActionContext(actionContext); | ||
} | ||
|
||
/** | ||
* Convert action context | ||
* | ||
* @param key the actionContext's key | ||
* @param value the actionContext's value | ||
* @param targetClazz the target class | ||
* @param <T> the target type | ||
* @return the action context of the target type | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
public static <T> T convertActionContext(String key, @Nullable Object value, @Nonnull Class<T> targetClazz) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.convertActionContext(key, value, targetClazz); | ||
|
||
} | ||
} |
77 changes: 77 additions & 0 deletions
77
compatible/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You 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.seata.rm.tcc.api; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* the TCC parameters that need to be passed to the action context; | ||
* <p> | ||
* add this annotation on the parameters of the try method, and the parameters will be passed to the action context | ||
* | ||
* @see org.apache.seata.spring.interceptor.ActionContextUtil | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target({ElementType.PARAMETER, ElementType.FIELD}) | ||
public @interface BusinessActionContextParameter { | ||
|
||
/** | ||
* parameter's name. Synonym for {@link #paramName()}. | ||
* | ||
* @return the name of the param or field | ||
* @see org.apache.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation | ||
*/ | ||
String value() default ""; | ||
|
||
/** | ||
* parameter's name. Synonym for {@link #value()}. | ||
* | ||
* @return the name of the param or field | ||
* @see org.apache.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation | ||
*/ | ||
String paramName() default ""; | ||
|
||
/** | ||
* if it is a sharding param ? | ||
* | ||
* @return the boolean | ||
* @deprecated This property is no longer in use. | ||
*/ | ||
@Deprecated | ||
boolean isShardingParam() default false; | ||
|
||
/** | ||
* Specify the index of the parameter in the List | ||
* | ||
* @return the index of the List | ||
* @see org.apache.seata.spring.interceptor.ActionContextUtil#getByIndex | ||
*/ | ||
int index() default -1; | ||
|
||
/** | ||
* whether get the parameter from the property of the object | ||
* if {@code index >= 0}, the object get from the List and then do get the parameter from the property of the object | ||
* | ||
* @return the boolean | ||
* @see org.apache.seata.spring.interceptor.ActionContextUtil#loadParamByAnnotationAndPutToContext | ||
* @see org.apache.seata.spring.interceptor.ActionContextUtil#fetchContextFromObject | ||
*/ | ||
boolean isParamInProperty() default false; | ||
} |