weird issue with PostConstruct in parent class - spring

I have such a simple example:
public class Base<T> {
private String value;
public Base(String value) {
this.value = value;
}
#PostConstruct
private void init() {
System.out.println(value);
}
}
public class StringTest extends Base<String> {
public StringTest(String value) {
super(value);
}
}
public class IntegerTest extends Base<Integer> {
public IntegerTest(String value) {
super(value);
}
}
#Configuration
public class Configuration {
#bean(name="stringtest1")
public Base<?> getStringTest1() {
return new StringTest("string test 1");
}
#bean(name="stringtest2")
public Base<?> getStringTest2() {
return new StringTest("string test 2");
}
#bean(name="integertest1")
public Base<?> getIntegerTest1() {
return new IntegerTest("integer test 1");
}
#bean(name="integertest2")
public Base<?> getIntegerTest2() {
return new IntegerTest("integer test 2");
}
}
The output is
string test 1
string test 2
PostConstruct is only invoked for beans stringtest1 and stringtest2 but not for integertest1 and integertest2.
If I change the configuration to below (change ? to the concrete type)
#bean(name="stringtest1")
public Base<String> getStringTest1() {
return new StringTest("string test 1");
}
#bean(name="stringtest2")
public Base<String> getStringTest2() {
return new StringTest("string test 2");
}
#bean(name="integertest1")
public Base<Integer> getIntegerTest1() {
return new IntegerTest("integer test 1");
}
#bean(name="integertest2")
public Base<Integer> getIntegerTest2() {
return new IntegerTest("integer test 2");
}
I will get the expected output:
string test 1
string test 2
integer test 1
integer test 2
Any idea why my previous code only have the PostConstruct invoked for the first 2 beans?

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?

Using Baggage in OpenTelemetry Spring application

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);
}

Use #Value on a conditional Bean

I'm providing a value via a conditional Bean. If the Condition is met everything is fine but if the condition is not met (hence the bean is not present) my code fails. is there some way to check if the bean is defined before hand. in SpEL ?
I tried something like
#{someBean? someBean.myValue:null} but it does not work.
See this answer for why this works...
#SpringBootApplication
public class So56189689Application {
public static void main(String[] args) {
SpringApplication.run(So56189689Application.class, args);
}
#Value("#{containsObject('foo') ? getObject('foo').foo : null}")
String foo;
#Bean
public ApplicationRunner runner() {
return args -> System.out.println(foo);
}
// #Bean
// public Foo foo() {
// return new Foo();
// }
public static class Foo {
private String foo = "bar";
public String getFoo() {
return this.foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
}
EDIT
The #root object of the SpEL Expression is a BeanExpressionContext, you can invoke containsObject() and getObject() methods on that context.
Here's the code from the BeanExpressionContext:
public boolean containsObject(String key) {
return (this.beanFactory.containsBean(key) ||
(this.scope != null && this.scope.resolveContextualObject(key) != null));
}
public Object getObject(String key) {
if (this.beanFactory.containsBean(key)) {
return this.beanFactory.getBean(key);
}
else if (this.scope != null){
return this.scope.resolveContextualObject(key);
}
else {
return null;
}
}

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;
}
};
}

Factory Pattern: Enum Parameter vs Explicit Method Name?

Say you have a factory that returns instances of ILightBulb. Two ways (there may be more) of implementing the factory are as follows:
Option 1 - Passing in an enum type
enum LightBulbType
{
Incandescent,
Halogen,
Led,
}
class ILightBulbFactory
{
public ILightBulb Create(LightBulbType type)
{
switch (type)
{
case LightBulbType.Incandescent:
return new IncandescentBulb();
case LightBulbType.Halogen:
return new HalogenBulb();
case LightBulbType.Led:
return new LedBulb();
}
}
}
Option 2 - Explicit method names
class ILightBulbFactory
{
public ILightBulb CreateIncandescent()
{
return new IncandescentBulb();
}
public ILightBulb CreateHalogen()
{
return new HalogenBulb();
}
public ILightBulb CreateLed()
{
return new LedBulb();
}
}
Which method is most preferable, and why?
Thanks.
In java, you can solve it in the enum, thus making sure that if you add new enums, all your code will remain working, instead of forgetting to add statements to your case.
enum LightBulbType
{
Incandescent{
#Override
public ILightBulb getInstance() {
return new IncandescentBulb();
}
},
Halogen{
#Override
public ILightBulb getInstance() {
return new HalogenBulb();
}
},
Led{
#Override
public ILightBulb getInstance() {
return new LedBulb();
}
};
public abstract ILightBulb getInstance();
}
class ILightBulbFactory
{
public ILightBulb Create(LightBulbType type)
{
return type.getInstance();
}
}
The equivalent for c# would be
public sealed class LightBulbType
{
public static readonly LightBulbType Incandescent = new
LightBulbType("Incandescent", new IncandescentBulb());
public static readonly LightBulbType Halogen = new
LightBulbType("Halogen", new HalogenBulb());
public static readonly LightBulbType LedBulb = new LightBulbType("Led",
new LedBulb());
public static IEnumerable<LightBulbType> Values
{
get
{
yield return Incandescent;
yield return Halogen;
yield return LedBulb;
}
}
private string Name { get; set; }
private ILightBulb Instance { get;}
private LightBulbType(string name, ILightBulb instance)
{
this.Name = name;
this.Instance = instance;
}
public override string ToString() => Name;
public ILightBulb GetInstance()
{
return Instance;
}
}
public interface ILightBulb
{
}
public class IncandescentBulb : ILightBulb
{
}
public class HalogenBulb : ILightBulb
{
}
public class LedBulb : ILightBulb
{
}
public static class LightBulbFactory
{
public static ILightBulb Create(LightBulbType type)
{
return type.GetInstance();
}
}
For call
ILightBulb halogenBulb = new HalogenBulb();
ILightBulb incandescentBulb = new IncandescentBulb();
ILightBulb ledBulb = new LedBulb();
or
ILightBulb halo = LightBulbFactory.Create(LightBulbType.Halogen);
ILightBulb inca = LightBulbFactory.Create(LightBulbType.Incandescent);
ILightBulb led = LightBulbFactory.Create(LightBulbType.LedBulb);

Resources