Using Baggage in OpenTelemetry Spring application - spring-boot

I have a spring boot application where i have instrumented my code using automatic instrumentation.
Now in my application i am trying to attach a baggage in the traces or some specific span.
I know it uses contextPropagation. but i am not able to implement how contextPropagator, baggage and span work together.
Here is my relevant code implementation:
#WithSpan
private void doSomeWorkNewSpan() {
logger.info("Doing some work In New span");
Span span = Span.current();
ContextPropagators contextPropagators = new ContextPropagators() {
#Override
public TextMapPropagator getTextMapPropagator() {
return null;
}
};
Context context = new Context() {
#Override
public <V> V get(ContextKey<V> contextKey) {
return null;
}
#Override
public <V> Context with(ContextKey<V> contextKey, V v) {
return null;
}
};
Baggage baggage = new Baggage() {
#Override
public int size() {
return 0;
}
#Override
public void forEach(BiConsumer<? super String, ? super BaggageEntry> biConsumer) {
}
#Override
public Map<String, BaggageEntry> asMap() {
return null;
}
#Override
public String getEntryValue(String s) {
return null;
}
#Override
public BaggageBuilder toBuilder() {
return null;
}
};
baggage.storeInContext(context);
// span.storeInContext();
span.setAttribute("crun","yes");
span.addEvent("app.processing2.start", atttributes("321"));
span.addEvent("app.processing2.end", atttributes("321"));
}
private Attributes atttributes(String id) {
return Attributes.of(AttributeKey.stringKey("app.id"), id);
}

Related

trino udf how to create a aggregate function for the window function

I tried to write a udf function to calculate my data. In the trino's docs, I knew I should to write a function plugin and I succeed to execute my udf aggregate function sql.
But when I write sql with aggregate function and window function, the sql executed failed.
The error log is com.google.common.util.concurrent.ExecutionError: java.lang.NoClassDefFoundError: com/example/ListState.
I think I may implement the interface about the window function.
The ListState.java file code
#AccumulatorStateMetadata(stateSerializerClass = ListStateSerializer.class, stateFactoryClass = ListStateFactory.class)
public interface ListState extends AccumulatorState {
List<String> getList();
void setList(List<String> value);
}
The ListStateSerializer file code
public class ListStateSerializer implements AccumulatorStateSerializer<ListState>
{
#Override
public Type getSerializedType() {
return VARCHAR;
}
#Override
public void serialize(ListState state, BlockBuilder out) {
if (state.getList() == null) {
out.appendNull();
return;
}
String value = String.join(",", state.getList());
VARCHAR.writeSlice(out, Slices.utf8Slice(value));
}
#Override
public void deserialize(Block block, int index, ListState state) {
String value = VARCHAR.getSlice(block, index).toStringUtf8();
List<String> list = Arrays.asList(value.split(","));
state.setList(list);
}
}
The ListStateFactory file code
public class ListStateFactory implements AccumulatorStateFactory<ListState> {
public static final class SingleListState implements ListState {
private List<String> list = new ArrayList<>();
#Override
public List<String> getList() {
return list;
}
#Override
public void setList(List<String> value) {
list = value;
}
#Override
public long getEstimatedSize() {
if (list == null) {
return 0;
}
return list.size();
}
}
public static class GroupedListState implements GroupedAccumulatorState, ListState {
private final ObjectBigArray<List<String>> container = new ObjectBigArray<>();
private long groupId;
#Override
public List<String> getList() {
return container.get(groupId);
}
#Override
public void setList(List<String> value) {
container.set(groupId, value);
}
#Override
public void setGroupId(long groupId) {
this.groupId = groupId;
if (this.getList() == null) {
this.setList(new ArrayList<String>());
}
}
#Override
public void ensureCapacity(long size) {
container.ensureCapacity(size);
}
#Override
public long getEstimatedSize() {
return container.sizeOf();
}
}
#Override
public ListState createSingleState() {
return new SingleListState();
}
#Override
public ListState createGroupedState() {
return new GroupedListState();
}
}
Thanks for help!!!!
And I found the WindowAccumulator class in the trino source code. But I don't know how to use it.
How to create a aggregate function for window function?

Best approach to use DiffUtil with LIveData + Room Database?

I am using Room Database with LiveData , but my Local Database is updating too fast as per our requirement and at the same time i have to reload my recycler view .instead of calling notifyDataSetChanged() to adapter , i am trying to use DiffUtil , but is crashing or not reloading properly , this is uncertain .
i am following this tutorial :
Tutorials Link here
MyAdapter :
public class SwitchGridAdapter extends RecyclerView.Adapter<SwitchGridAdapter.ViewHolder> {
private List<Object> allItemsList;
private LayoutInflater mInflater;
private OnItemClickListener mClickListener;
private Context context;
private Queue<List<Object>> pendingUpdates =
new ArrayDeque<>();
// data is passed into the constructor
public SwitchGridAdapter(Context context,List<Appliance> applianceList,List<ZmoteRemote> zmoteRemoteList) {
this.mInflater = LayoutInflater.from(context);
this.context = context;
allItemsList = new ArrayList<>();
if (applianceList!=null) allItemsList.addAll(applianceList);
if (zmoteRemoteList!=null)allItemsList.addAll(zmoteRemoteList);
}
// inflates the cell layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R .layout.switch_grid_item, parent, false);
return new ViewHolder(view);
}
// binds the data to the textview in each cell
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Doing some update with UI Elements
}
// total number of cells
#Override
public int getItemCount() {
return allItemsList.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,View.OnLongClickListener {
TextView myTextView;
ImageView imgSwitch;
ViewHolder(View itemView) {
super(itemView);
myTextView = (TextView) itemView.findViewById(R.id.txtSwitchName);
imgSwitch = (ImageView) itemView.findViewById(R.id.imgSwitchStatus);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
#Override
public void onClick(View view) {
// handling click
}
#Override
public boolean onLongClick(View view) {
return true;
}
// convenience method for getting data at click position
Object getItem(int id) {
return allItemsList.get(id);
}
// allows clicks events to be caught
public void setClickListener(OnItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongPressListner(View view, int position);
}
// ✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
// From This Line Reloading with Diff Util is Done .
//✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
public void setApplianceList( List<Appliance> applianceList,List<ZmoteRemote> zmoteRemoteList)
{
if (allItemsList == null)
allItemsList = new ArrayList<>();
List<Object> newAppliances = new ArrayList<>();
if (applianceList!=null) newAppliances.addAll(applianceList);
updateItems(newAppliances);
}
// when new data becomes available
public void updateItems(final List<Object> newItems) {
pendingUpdates.add(newItems);
if (pendingUpdates.size() > 1) {
return;
}
updateItemsInternal(newItems);
}
// This method does the heavy lifting of
// pushing the work to the background thread
void updateItemsInternal(final List<Object> newItems) {
final List<Object> oldItems = new ArrayList<>(this.allItemsList);
final Handler handler = new Handler();
new Thread(new Runnable() {
#Override
public void run() {
final DiffUtil.DiffResult diffResult =
DiffUtil.calculateDiff(new DiffUtilHelper(oldItems, newItems));
handler.post(new Runnable() {
#Override
public void run() {
applyDiffResult(newItems, diffResult);
}
});
}
}).start();
}
// This method is called when the background work is done
protected void applyDiffResult(List<Object> newItems,
DiffUtil.DiffResult diffResult) {
dispatchUpdates(newItems, diffResult);
}
// This method does the work of actually updating
// the backing data and notifying the adapter
protected void dispatchUpdates(List<Object> newItems,
DiffUtil.DiffResult diffResult) {
// ❌❌❌❌❌❌ Next Line is Crashing the app ❌❌❌❌❌
pendingUpdates.remove();
dispatchUpdates(newItems, diffResult);
if (pendingUpdates.size() > 0) {
updateItemsInternal(pendingUpdates.peek());
}
}
}
Observing LiveData
public void setUpAppliancesListLiveData()
{
if (applianceObserver!=null)
{
applianceObserver = null;
}
Log.e("Appliance Fetch","RoomName:"+this.roomName);
applianceObserver = new Observer<List<Appliance>>() {
#Override
public void onChanged(#Nullable List<Appliance> applianceEntities) {
// Log.e("Appliance Result","Appliance List \n\n:"+applianceEntities.toString());
new Thread(new Runnable() {
#Override
public void run() {
List<Appliance> applianceListTemp = applianceEntities;
zmoteRemoteList = new ArrayList<>(); //appDelegate.getDatabase().zmoteRemoteDao().getRemoteList(roomName);
// Sort according to name
Collections.sort(applianceListTemp, new Comparator<Appliance>() {
#Override
public int compare(Appliance item, Appliance t1) {
String s1 = item.getSwitchName();
String s2 = t1.getSwitchName();
return s1.compareToIgnoreCase(s2);
}
});
if(getActivity()!=null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
applianceList = applianceListTemp;
mRecyclerView.getRecycledViewPool().clear();
adapter.setApplianceList(applianceList,zmoteRemoteList);
}
});
}
}
}).start();
}
};
appDelegate.getDatabase().applianceDao().getApplinaceListByRoomName(this.roomName).observe(this, applianceObserver);
}

How to make Hibernate use setFixedCHAR instead of setString

Can I somehow modify the way Hibernate binds parameters to the query?
For example, I want hibernate to use OracleResultSet.setFixedChar() when executing on an string column, instead of rs.setString() when executing a JPA query via Spring data.
This is how I would do it without Hibernate:
try(PreparedStatement ps = con.executeQuery("...")) {
if(ps.isWrapped(OraclePreparedStatement.class) {
ps.unwrap(OraclePreparedStatement.class).setFixedCHAR(0, myStringField);
} else {
ps.setString(0, myStringField);
}
try(ResultSet rs = ps.getResultSet()) {
while(rs.next()) {
... do stuff ...
}
}
}
Repository method (Spring data JPA):
List<Object> findByMyStringField(String myStringField);
How can I influence how Hibernate binds my variable. With the above example setString is used always.
As background: the problem is that all our Legacy DB's use CHAR columns and not VARCHAR2, so we have to deal with whitespace and setFixedCHAR should do exactly what we would want.
Found a solution by implementing a SqlTypeDescriptor & Custom Dialect:
#Autowired
private DataSource source;
#Bean
public HibernateJpaVendorAdapter getHibernateJPAVendorAdapter() {
return new CustomHibernateJpaVendorAdaptor();
}
private static class CustomHibernateJpaVendorAdaptor extends HibernateJpaVendorAdapter {
#Override
protected Class<?> determineDatabaseDialectClass(Database database) {
// if HSQL is copied from Spring Sourcecode to keep everything the same
if (Database.HSQL.equals(database)) {
return CustomHsqlDialect.class;
}
try {
if (source.isWrapperFor(OracleDataSource.class)) {
return CustomOracleDialect.class;
}
} catch (SQLException e) {
}
return super.determineDatabaseDialectClass(database);
}
private class CustomHsqlDialect extends HSQLDialect {
public CustomHsqlDialect() {
registerColumnType(Types.BOOLEAN, "boolean");
registerHibernateType(Types.BOOLEAN, "boolean");
}
}
}
#NoArgsConstructor
public static class CustomOracleDialect extends Oracle12cDialect {
private static final OracleCharFix INSTANCE = new OracleCharFix();
#Override
protected SqlTypeDescriptor getSqlTypeDescriptorOverride(final int sqlCode) {
switch (sqlCode) {
case Types.VARCHAR:
return INSTANCE;
default:
return super.getSqlTypeDescriptorOverride(sqlCode);
}
}
}
#Slf4j
private static class OracleCharFix extends CharTypeDescriptor {
#Override
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<>(javaTypeDescriptor, this) {
#Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
if (st.isWrapperFor(OraclePreparedStatement.class)) {
OraclePreparedStatement ops = st.unwrap(OraclePreparedStatement.class);
if (ops.getParameterMetaData().getParameterType(index) == Types.CHAR) {
ops.setFixedCHAR(index, javaTypeDescriptor.unwrap(value, String.class, options));
} else {
st.setString(index, javaTypeDescriptor.unwrap(value, String.class, options));
}
} else {
st.setString(index, javaTypeDescriptor.unwrap(value, String.class, options));
}
}
#Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
//Is nolonger used by Hibernate in the current Version
st.setString(name, javaTypeDescriptor.unwrap(value, String.class, options));
}
private boolean checkIfCHARByName(ResultSetMetaData metadata, String name)
throws SQLException {
for (int i = 1; i <= metadata.getColumnCount(); i++) {
if (metadata.getColumnType(i) == Types.CHAR && Objects.equals(metadata.getColumnName(i), name)) {
return true;
}
}
return false;
}
};
}

Adding a new field to body of the request from Netflix Zuul Pre-filter

I'm trying to add a new field to request's body, in a Zuul Pre-filter.
I'm using one of the Neflix's Zuul sample projects from here, and my filter's implementation is very similar to UppercaseRequestEntityFilter from this sample.
I was able to apply a transformation such as uppercase, or even to completely modify the request, the only inconvenient is that I'm not able to modify the content of body's request that has a length more than the original length of the body's request.
This is my filter's implementation:
#Component
public class MyRequestEntityFilter extends ZuulFilter {
public String filterType() {
return "pre";
}
public int filterOrder() {
return 10;
}
public boolean shouldFilter() {
RequestContext context = getCurrentContext();
return true;
}
public Object run() {
try {
RequestContext context = getCurrentContext();
InputStream in = (InputStream) context.get("requestEntity");
if (in == null) {
in = context.getRequest().getInputStream();
}
String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
body = body.replaceFirst("qqq", "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq");
// body = body.toUpperCase();
context.set("requestEntity", new ServletInputStreamWrapper(body.getBytes("UTF-8")));
}
catch (IOException e) {
rethrowRuntimeException(e);
}
return null;
}
}
This is the request that I'm doing:
This is the response that I'm receiving:
I was able to obtain what I wanted, using the implementation of PrefixRequestEntityFilter, from sample-zuul-examples:
#Component
public class MyRequestEntityFilter extends ZuulFilter {
public String filterType() {
return "pre";
}
public int filterOrder() {
return 10;
}
public boolean shouldFilter() {
RequestContext context = getCurrentContext();
return true;
}
public Object run() {
try {
RequestContext context = getCurrentContext();
InputStream in = (InputStream) context.get("requestEntity");
if (in == null) {
in = context.getRequest().getInputStream();
}
String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
body = body.replaceFirst("qqq", "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq");
byte[] bytes = body.getBytes("UTF-8");
context.setRequest(new HttpServletRequestWrapper(getCurrentContext().getRequest()) {
#Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStreamWrapper(bytes);
}
#Override
public int getContentLength() {
return bytes.length;
}
#Override
public long getContentLengthLong() {
return bytes.length;
}
});
}
catch (IOException e) {
rethrowRuntimeException(e);
}
return null;
}
}

Initial data on JPA repositories

I'm looking for a convenient way to provide initial data for my application. Currently I've implemented a Spring Data JPA based project which is my foundation of all database related operation.
Example:
I've got a entity Role which can be assigned to the entity User. On a clean application start I would like to provide directly some default roles (e.g. admin, manager, etc).
Best
I built a random data factory :
public class RandomDataFactory {
private static final String UNGENERATED_VALUE_MARKER = "UNGENERATED_VALUE_MARKER";
private static void randomlyPopulateFields(Object object) {
new RandomValueFieldPopulator().populate(object);
}
/**
* Instantiates a single object with random data
*/
public static <T> T getSingle(Class<T> clazz) throws IllegalAccessException, InstantiationException {
T object = clazz.newInstance();
randomlyPopulateFields(object);
return object;
}
/**
* Returns an unmodifiable list of specified type objects with random data
*
* #param clazz the myPojo.class to be instantiated with random data
* #param maxLength the length of list to be returned
*/
public static <T> List<T> getList(Class<T> clazz, int maxLength) throws IllegalAccessException, InstantiationException {
List<T> list = new ArrayList<T>(maxLength);
for (int i = 0; i < maxLength; i++) {
T object = clazz.newInstance();
randomlyPopulateFields(object);
list.add(i, object);
}
return Collections.unmodifiableList(list);
}
/**
* Returns a unmodifiable list of specified type T objects with random data
* <p>List length will be 3</p>
*
* #param clazz the myPojo.class to be instantiated with random data
*/
public static <T> List<T> getList(Class<T> clazz) throws InstantiationException, IllegalAccessException {
return getList(clazz, 3);
}
public static <T> T getPrimitive(Class<T> clazz) {
return (T) RandomValueFieldPopulator.generateRandomValue(clazz);
}
public static <T> List<T> getPrimitiveList(Class<T> clazz) {
return getPrimitiveList(clazz, 3);
}
public static <T> List<T> getPrimitiveList(Class<T> clazz, int length) {
List<T> randoms = new ArrayList<T>(length);
for (int i = 0; i < length; i++) {
randoms.add(getPrimitive(clazz));
}
return randoms;
}
private static class RandomValueFieldPopulator {
public static Object generateRandomValue(Class<?> fieldType) {
Random random = new Random();
if (fieldType.equals(String.class)) {
return UUID.randomUUID().toString();
} else if (Date.class.isAssignableFrom(fieldType)) {
return new Date(System.currentTimeMillis() - random.nextInt());
} else if (LocalDate.class.isAssignableFrom(fieldType)) {
Date date = new Date(System.currentTimeMillis() - random.nextInt());
return new LocalDate(date);
} else if (fieldType.equals(Character.class) || fieldType.equals(Character.TYPE)) {
return (char) (random.nextInt(26) + 'a');
} else if (fieldType.equals(Integer.TYPE) || fieldType.equals(Integer.class)) {
return random.nextInt();
} else if (fieldType.equals(Short.TYPE) || fieldType.equals(Short.class)) {
return (short) random.nextInt();
} else if (fieldType.equals(Long.TYPE) || fieldType.equals(Long.class)) {
return random.nextLong();
} else if (fieldType.equals(Float.TYPE) || fieldType.equals(Float.class)) {
return random.nextFloat();
} else if (fieldType.equals(Double.TYPE)) {
return random.nextInt(); //if double is used, jsonPath uses bigdecimal to convert back
} else if (fieldType.equals(Double.class)) {
return random.nextDouble(); //if double is used, jsonPath uses bigdecimal to convert back
} else if (fieldType.equals(Boolean.TYPE) || fieldType.equals(Boolean.class)) {
return random.nextBoolean();
} else if (fieldType.equals(BigDecimal.class)) {
return new BigDecimal(random.nextFloat());
} else if (Enum.class.isAssignableFrom(fieldType)) {
Object[] enumValues = fieldType.getEnumConstants();
return enumValues[random.nextInt(enumValues.length)];
} else if (Number.class.isAssignableFrom(fieldType)) {
return random.nextInt(Byte.MAX_VALUE) + 1;
} else {
return UNGENERATED_VALUE_MARKER;
}
public void populate(Object object) {
ReflectionUtils.doWithFields(object.getClass(), new RandomValueFieldSetterCallback(object));
}
private static class RandomValueFieldSetterCallback implements ReflectionUtils.FieldCallback {
private final Object targetObject;
public RandomValueFieldSetterCallback(Object targetObject) {
this.targetObject = targetObject;
}
#Override
public void doWith(Field field) throws IllegalAccessException {
Class<?> fieldType = field.getType();
if (!Modifier.isFinal(field.getModifiers())) {
Object value = generateRandomValue(fieldType);
if (!value.equals(UNGENERATED_VALUE_MARKER)) {
ReflectionUtils.makeAccessible(field);
field.set(targetObject, value);
}
}
}
}
}
}
Look into an in-memory H2 database.
http://www.h2database.com/html/main.html
Maven Dependency
<!-- H2 Database -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.178</version>
</dependency>
Spring Java Config Entry
#Bean
public DataSource dataSource() {
System.out.println("**** USING H2 DATABASE ****");
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.H2).addScript("/schema.sql").build();
}
You can create/load the H2 database w/ a SQL script in the above code using .addscript().
If you are using it for Unit test, and need a different state for different test, then
There is a http://dbunit.sourceforge.net/
Specifically for Spring there is http://springtestdbunit.github.io/spring-test-dbunit/
If you need to initialize it only once and using EmbeddedDatabaseBuilder for testing, then as Brandon said, you can use EmbeddedDatabaseBuilder.
#Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.H2).addScript("/schema.sql").build();
}
If you want it to be initialised on application start, you can add #PostConstruct function to your Configuration bean, and it will be initialised after configuration bean was created.
#PostConstruct
public void initializeDB() {
}

Resources