Spring Expression Directly access map keys in Selection - spring

Consider that I have parsed a JSON String to a Map<String, Object>, which is arbitrarily nested
My JSON looks like:
{
"root": [
{"k":"v1"},
{"k":"v2"}
]
}
I tried the expression root.?[k == 'v1'], however received the following error:
EL1008E: Property or field 'k' cannot be found on object of type 'java.util.LinkedHashMap' - maybe not public?

The evaluation context needs a MapAccessor:
public static void main(String[] args) throws Exception {
String json = "{\n" +
" \"root\": [\n" +
" {\"k\":\"v1\"},\n" +
" {\"k\":\"v2\"}\n" +
" ]\n" +
"}";
ObjectMapper mapper = new ObjectMapper();
Object root = mapper.readValue(json, Object.class);
Expression expression = new SpelExpressionParser().parseExpression("root.?[k == 'v1']");
StandardEvaluationContext ctx = new StandardEvaluationContext();
ctx.addPropertyAccessor(new MapAccessor());
System.out.println(expression.getValue(ctx, root));
}
result:
[{k=v1}]
Without a MapAccessor, you need
"['root'].?[['k'] == 'v1']"
A MapAccessor will only work with map keys that don't contain periods.

Related

MessageBodyWriter not found StreamingBodyResponse

I am trying to make StreamResponseBody work with sample hardcoded data.
#POST
#Path("filetypecsv")
#Produces("text/plain")
public ResponseEntity<StreamingResponseBody> studentsFile() {
String name = "name";
String rollNo = "rollNo";
StreamingResponseBody stream = output -> {
Writer writer = new BufferedWriter(new OutputStreamWriter(output));
writer.write("name,rollNo"+"\n");
for (int i = 1; i <= 1000; i++) {
writer.write(name + i + " ," + rollNo + i + "\n");
writer.flush();
}
};
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=students.csv")
.contentType(org.springframework.http.MediaType.TEXT_PLAIN)
.body(stream);
}
I am always getting this error :
SEVERE: MessageBodyWriter not found for media type=text/plain, type=class org.springframwork.http.ResponseEntity, genericType=org.springframework.http.ReponseEntity<StreamingResponseBody>.
I have added the dependency : jersey-media-json-jackson.
But I am still getting this error, please advise.
This solution applies if your code is using Jax.rs.core and not Spring #RestController. I have not seen a solution where you can use Springs StreamingResponseBody along with jax.rs
But instead you can use jax.rs StreamingOutput. You can return a jax.rs Response, and (MediaType.TEXT_PLAIN) or equivalent like an octet stream.
Please see this link - https://dzone.com/articles/jax-rs-streaming-response
StreamingOutput stream = new StreamingOutput() {
#Override
public void write(OutputStream os) throws IOException, WebApplicationException {
Writer writer = new BufferedWriter(new OutputStreamWriter(os));
for (org.neo4j.graphdb.Path path : paths) {
writer.write(path.toString() + "\n");
}
writer.flush();
}
};
return Response.ok(stream).build();

Spring Aspect to log exceptions [duplicate]

This question already has an answer here:
Exception handling and after advice
(1 answer)
Closed 1 year ago.
I added aspect like below in my spring-boot REST API to log calls to all methods in package "com.leanring.sprint" like so:
#Aspect
#Component
public class LogAdvice {
Logger logger = LoggerFactory.getLogger(LogAdvice.class);
#Pointcut(value = "execution(* com.learning.spring.*.*.*(..))")
public void pointCut() {
}
#Around("pointCut()")
public Object appLogger(ProceedingJoinPoint jp) throws Throwable {
ObjectMapper mapper = new ObjectMapper();
String methodName = jp.getSignature().getName();
String className = jp.getTarget().getClass().toString();
Object[] args = jp.getArgs();
logger.info("Start call: " + className + ":" + methodName + "()" + " with arguments: " + mapper.writeValueAsString(args));
Object object = jp.proceed();
logger.info("End call: " + className + ":" + methodName + "()" + " returned: " + mapper.writeValueAsString(object));
return object;
}
}
This is working fine, but I would also like it to be able to log any exceptions that could occur when a method is called.
How do I do that?
I suppose you could add another #AfterThrowing advice using the same pointcut or wrap jp.proceed(); inside a try-catch block.

jersey ContainerRequestFilter : getPathParameters gives empty values

I have an authorization filter. While trying to retrieve pathparameters, I am unable to get the values.
could someone please tell me, what is wrong with the below code.
#AuthorizedAccess //named exception
#Provider
public class AuthorizedAccessFilter implements ContainerRequestFilter {
/** The Constant logger. */
private final static Logger logger = LoggerFactory.getLogger(AuthorizedAccessFilter.class);
public void filter(ContainerRequestContext requestContext) {
logger.info(AUTH_MESSAGE, requestContext.getUriInfo().getAbsolutePath());
MultivaluedMap<String, String> pathParameters = requestContext.getUriInfo().getPathParameters();
for (Entry<String, List<String>> e : pathParameters.entrySet()) {
logger.info( " key :value " +e.getKey(), e.getValue());
}
logger.info("pathparammap = {} ",pathParameters.size());
}
and it returns:
it returns key name but it doesn't return the value.
AuthorizedAccessFilter - key value entity-id
AuthorizedAccessFilter - pathparammap = 1
Well it looks like a simple incorrect format (1-st argument) in logger. You need to specify at least one {} that would be replaced with value of 2-nd logger.info argument
logger.info( " key :value {}" + e.getKey(), e.getValue());
or
logger.info( " key :value {} {}" , e.getKey() , e.getValue());
Also take a look at SLF4J documentation

Is it worked Nashorn JS object to java.util.Map?

I have java method
void someMethod(String str, Map map) {
...
}
From JS call this method
var map = new Object()
map.key1 = "val1"
...someMethod(str, map)
Exception:
java.lang.NoSuchMethodException: None of the fixed arity signatures
[(java.lang.String, java.util.Map)] of method org.prjctor.shell.Bash.eval
match the argument types [java.lang.String, jdk.nashorn.internal.scripts.JO]
But in Nashorn docs "Mapping of Data Types Between Java and JavaScript" said "Every JavaScript object is also a java.util.Map so APIs receiving maps will receive them directly".
What am I doing wrong?
Agree with the previous answers that you cannot do this as the docs have implied.
However you could create and pass a map as follows
..
var HashMap = Java.type('java.util.HashMap');
var map = new HashMap();
map.put('1', 'val1');
...someMethod(str, map)
The doc says ""Every JavaScript object implements the java.util.Map interface". But this sample test program shows thats not the case.
public final class NashornTestMap {
public static void main(String args[]) throws Exception{
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine nashorn = factory.getEngineByName("nashorn");
nashorn.eval(""
+"load(\"nashorn:mozilla_compat.js\");"
+ "importClass(Packages.NashornTestMap);"
+ "var map={};"
+ "map[\"Key\"]=String(\"Val\"); "
+ "var test = new NashornTestMap();"
+ "test.test(map);"
+ "");
}
public void test(Map<String, String> obj){
System.out.println(obj);
}
}
The above code give exception "Exception in thread "main" java.lang.ClassCastException: Cannot cast jdk.nashorn.internal.scripts.JO4 to java.util.Map". This link confirms this.
However you can use Map inside your script and call the java objects directly, like this.
public final class NashornTestMap {
public static void main(String args[]) throws Exception{
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine nashorn = factory.getEngineByName("nashorn");
nashorn.eval(""
+"load(\"nashorn:mozilla_compat.js\");"
+ "importClass(Packages.NashornTestMap);"
+ "var HashMap = Java.type(\"java.util.HashMap\");"
+ "var map = new HashMap();"
+ "map.put(0, \"value1\");"
+ "var test = new NashornTestMap();"
+ "test.test(map);"
+ "");
}
public void test(Map<String, String> obj){
System.out.println(obj);
}
}
Returns "{0=value1}"

Postgres Parameter Query for SimpleJdbcTemplate

I am trying to execute a parameter query for a Postgre database using Springs SimpleJdbcTemplate. My class that calls the query looks like this:
public class GeoCodeServiceImpl extends SimpleJdbcDaoSupport implements GeoCodeServiceInterface {
public static final String SELECT_STATEMENT = "SELECT ste_code, ste_code_type, name, fips_code " +
"FROM \"steGeo\" " +
"WHERE st_contains( the_geom, ST_GeomFromText('POINT(:lon :lat)',4269))";
public List<GeoCode> getGeoResults(Double lon, Double lat) throws DataAccessException {
MapSqlParameterSource mappedParms = new MapSqlParameterSource("lon", lon.toString());
mappedParms.addValue("lat", lat.toString());
SqlParameterSource namedParms = mappedParms;
List<GeoCode> resultList = getSimpleJdbcTemplate().query(SELECT_STATEMENT, new GeoCodeRowMapper(), namedParms);
if (resultList == null || resultList.size() == 0) {
logger.warn("No record found in GeoCode lookup.");
}
return resultList;
}
protected static final class GeoCodeRowMapper implements RowMapper<GeoCode> {
public GeoCode mapRow(ResultSet rs, int i) throws SQLException {
GeoCode gc = new GeoCode();
gc.setCode(rs.getString(1));
gc.setType(rs.getString(2));
gc.setFips(rs.getString(3));
gc.setName(rs.getString(4));
return gc;
}
}
}
I am testing the query with this class:
public class GeoCodeServiceTest {
public static void main(String[] args) {
Double lat = 40.77599;
Double lon = -83.82322;
String[] cntxs = {"project-datasource-test.xml","locationService-context.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(cntxs);
GeoCodeServiceImpl impl = ctx.getBean("geoCodeService", GeoCodeServiceImpl.class);
List<GeoCode> geoCodes = impl.getGeoResults(lon, lat);
System.out.println(geoCodes);
}
}
I keep getting the following error:
2011-03-07 08:16:29,227 [main] DEBUG org.springframework.jdbc.support.SQLErrorCodesFactory - SQL error codes for 'PostgreSQL' found
2011-03-07 08:16:29,227 [main] DEBUG org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator - Unable to translate SQLException with SQL state 'XX000', error code '0, will now try the fallback translator
2011-03-07 08:16:29,227 [main] DEBUG org.springframework.jdbc.support.SQLStateSQLExceptionTranslator - Extracted SQL state class 'XX' from value 'XX000'
Exception in thread "main" org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [SELECT ste_code, ste_code_type, name, fips_code FROM "steGeo" WHERE st_contains( the_geom, ST_GeomFromText('POINT(:lon :lat)',4269))]; SQL state [XX000]; error code [0]; ERROR: parse error - invalid geometry
Hint: "POINT(" <-- parse error at position 6 within geometry; nested exception is org.postgresql.util.PSQLException: ERROR: parse error - invalid geometry
Hint: "POINT(" <-- parse error at position 6 within geometry
It looks like my parameters are not populated.
I haven't used Postgre before so any help would be much appreciated.
Thanks
Parameters are not handled inside quoted strings, so I guess you need to pass the whole string as a single parameter:
public static final String SELECT_STATEMENT =
"SELECT ste_code, ste_code_type, name, fips_code " +
"FROM \"steGeo\" " +
"WHERE st_contains( the_geom, ST_GeomFromText(:pt, 4269))";
...
MapSqlParameterSource mappedParms = new MapSqlParameterSource("pt",
"POINT(" + lon.toString() + " " + lat.toString() + ")");

Resources