I use SpringBoot for REST web services development and SonarQube for static analysis.
I have a few endpoints in my application that look the following way:
#PostMapping
ResponseEntity<?> addSomething(#RequestBody Some object) {
// some code there
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
SonarQube complains about using ResponseEntity with a wildcard, reporting me a Critical issue "Generic wildcard types should not be used in return parameters".
I wonder if I should disable this verification in SonarQube or come up with something different for return type for these cases.
What do you think about it?
#PostMapping
ResponseEntity<Object> addSomething(#RequestBody Some object) {
// some code there
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
This will also remove the error. It is still very generic, but it is one of the solutions if you want to return different types based on the outcome. For instance:
#PostMapping
ResponseEntity<Object> addSomething(#RequestBody Some object) {
//Will return ResponseEntity<> with errors
ResponseEntity<Object> errors = mapValidationService(bindingResult);
if (!ObjectUtils.isEmpty(errors)) return errors;
// some code there
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
So actually i find the rule pretty self describing:
Using a wildcard as a return type implicitly means that the return value should be considered read-only, but without any way to enforce this contract.
Let's take the example of method returning a "List". Is it possible on this list to add a Dog, a Cat, ... we simply don't know. The consumer of a method should not have to deal with such disruptive questions.
https://sonarcloud.io/organizations/default/rules#rule_key=squid%3AS1452
So Actually in your case, you do not want any kind of Class in there, you specifically want an Serializable-object - for obvious reasons: it should be serialized later on
So instead of using ? it would be more suitable in your case to use Serializable. This is always case dependent, but normally you definitly expect some kind of common interface or base class as a return value. Hence that, the follow up developer, definitly knows what he can expect, and what kind of functionality he definitly can use.
Finally I've removed <?> from return value, so the code looks like the following now:
#PostMapping
ResponseEntity addSomething(#RequestBody Some object) {
// some code there
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
SonarQube doesn't complain anymore and code seems a little bit simpler now.
Related
I have a symfony bundle which needs to store a lot of data. Currently said data is stored as arrays, read and put into the memory of a service. While this approach works, it's not very readable.
It's not possible to simply set an argument to a list of X, as such I'm unable to store said data in a better way.
My data will not change between cache compiles, so I was wondering if there's anything where I can do something like the following
class MyModel {
public function __construct(
public readonly string $from,
public readonly string $to
) {}
}
// on compiler pass
$model = new MyModel('aaa', 'bbbb');
$myDefinition->addMethodCall('myMethod', [[$model], $otherScalarArguments]);
I was also wondering if Symfony's expressions could help in this case, but I'm unsure.
My current use of ->addMethodCall has 7 arguments, so this would make my life easier.
At first I thought the container could handle this sort of thing so I reproduced the issue and got:
Unable to dump a service container if a parameter is an object or a resource.
So even though you can pass an object as an argument, the caching code which writes the compiled container out as a php file is not smart enough to handle it. Note: it is often useful to add error messages to questions.
The trick is to serialize the object in the pass itself and then unserialize it in the service.
class MyService
{
private MyModel $myModel;
public function __construct(string $myModel)
{
$this->myModel = unserialize($myModel);
dump($this->myModel);
}
}
# pass
$model = serialize(new MyModel('aaa', 'bbbb'));
$def = $container->getDefinition(MyService::class);
$def->addArgument($model);
I tested it and it all seemed to work. I did take take the liberty of simplifying the original code a bit but it will work work just fine for addMethodCall as well.
Might be worthwhile proposing this to the Symfony core group. It is niche functionality but might come in handy now and then.
I'm trying to implement an abstract base class for objects that will be parsed from HTTP calls. The goals is to create a CachedFuture<T> class that, when accessed, makes an HTTP call to get the object and caches the result.
My inclination was to implement the classes as follows:
class HTTPGetable<T extends HTTPGetable<T>> {
static Future<T> httpGet(int id);
}
class CachedFuture<T extends HTTPGetable<T>> {
int _id;
Future<T?>? _cachedResult;
bool _has_already_made_request;
CachedFuture({required int this._id});
Future<T?> get() {
if(this._cachedResult == null)
try {
this._cachedResult = T.httpGet(this._id);
} except {
// parse error or other error
this._cachedResult = CompletableFuture.completedFuture(null);
}
}
return this._cachedResult;
}
}
The intuition here is that there are a lot of objects with "pointers" to other objects in the database on the backend. It doesn't make sense to follow every pointer when constructing objects to return in the HttpRequest, so my intent is to wrap "pointers" in this CachedFuture class.
This should enable someone to "follow" one of these "pointers" without ever having to worry about caching the http request or about the specifics of constructing that request. Hopefully this provides another level of abstraction for the user of the class so they can right code that's agnostic to what's going on under the hood.
However, static interfaces aren't in Dart, so this pattern doesn't work. My intuition is that this is a sign I should be using a different pattern instead of trying to force my way.
httpGet is basically a factory method, but the functionality of CachedFuture needs a way to look up the factory from the type, so I don't immediately see a good way to implement a true factory either.
Could anyone recommend a good programming pattern for solving this? I imagine it's a pretty common usecase for both http requests and database requests.
Update: The best workaround I've found is to do different "factories" to httpGet each T, then use reflection to look up the appropriate factory. However, as the description sounds, this seems pretty convoluted & error prone, so I'm still convinced that there's almost certainly a better pattern to use.
Can't you just create the abstract class CachedFuture along the lines of what you wrote, with an abstract method httpGet(int id) to be implemented by the subclass?
If there is only ever one instance of an object of type <T extends CachedFuture> then you could consider making the subclass a Singleton.
Apologies if I misunderstood your question!
As both of them can be used for retrieving cookie through name string, I would like to know if there is any difference between them.
A great way to answer a question like this yourself, for the .NET Framework, is to make use of the Microsoft Reference Source. This lets you see and navigate through the source for the .NET Framework.
Looking at this, Request.Cookies returns an HttpCookieCollection and Request.Cookies.Get is therefore a method on HttpCookieCollection.
The most useful part of the code is for the indexer on HttpCookieCollection that retrieves a cookie by name:
public HttpCookie this[String name]
{
get { return Get(name);}
}
As you can see from that, this calls into the Get(string name) method, meaning that using the Request.Cookies(name) indexer is fundamentally the same as using Request.Cookies.Get(name) as one calls the other.
It is worth mentioning that anything you see here is an implementation detail that's subject to change. You should rely on documented behaviour, not on anything you discover through digging through the code, no matter how informative and interesting it is!
In my SharePoint code, I have the following line:
SPWeb web = site.RootWeb; //site is an SPSite object
When I rebuild my project and run the SPDispose tool on the assembly, I get the following error:
Module: Blah.SharePoint.Features.Core.dll Method:
Blah.SharePoint.Features.Core.Helpers.FeatureDeploymentHelper.RemoveWebPartFiles(Microsoft.SharePoint.SPFeatureReceiverProperties,System.String)
Statement: web := site.{Microsoft.SharePoint.SPSite}get_RootWeb()
Source:
C:\xxx\xxx\Main\Source\SharePoint\Features\Core\Helpers\FeatureDeploymentHelper.cs
Line: 26
Notes: Disposable type not disposed: Microsoft.SharePoint.SPWeb
***This may be a false positive depending on how the type was created or if it is disposed outside the current scope More Information:
http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_140
What I want to do is to have the SPDispose tool ignore this error, so I have pulled the SPDisposeCheckIgnore class and supporting enum into my project, and I've decorated my method appropriately:
[SPDisposeCheckIgnore(SPDisposeCheckID.SPDisposeCheckID_140, "RootWeb does not need disposed.")]
public static void RemoveWebPartFiles(SPFeatureReceiverProperties properties, string assemblyName)
{
...
}
After doing all of this, I still receive the error. Anyone know how I might go about getting rid of that error?
Two things need to be done here.
1) The SPDisposeCheckIgnore class must be defined in the SPDisposeCheck namespace. You CANNOT have your own namespace. See the related comment on this page: http://archive.msdn.microsoft.com/SPDisposeCheck/
2) Anything you are trying to ignore within RunWithElevatedPrivleges must be pulled into an external method or it will not be recognized. This was not being done in the example above, but was being done in other places.
These two rules must be followed for ignore to work. Hope this helps someone else down the road.
Double check how you're retrieving and assigning the RootWeb object. If it's done in an external method, the DisposeChecker might not pick up that it's a RootWeb reference.
I don't see anything wrong with what you've written. I pulled out getting the root web into a static method so I only had to ignore this error in one place, and it works in anonymous delegates. The following worked for me:
public class DisposeUtils
{
[SPDisposeCheckIgnore(SPDisposeCheckID.SPDisposeCheckID_140, "RootWeb does not need disposed. http://blogs.msdn.com/b/rogerla/archive/2009/11/30/sharepoint-2007-2010-do-not-dispose-guidance-spdisposecheck.aspx")]
public static SPWeb GetRootWeb(SPSite site)
{
return site.RootWeb;
}
}
Sorry, I'm not sure if that helps exactly - I'm saying your code should work. Have you checked SPDisposeCheck to see how it handles 'Documented' and 'Undocumented' errors? (I've never been entirely clear what those settings do)
I've been tinkering with IExternalizable, but I've noticed some unexpected behavior. I've got this class:
public function readExternal(input:IDataInput):void {
input.readObject();
input.readObject();
input.readObject();
}
public function writeExternal(output:IDataOutput):void {
output.writeObject("first string");
output.writeObject(424242);
output.writeObject("second string");
}
But when I try to serialize this class using AMF and send it to a remote server (via RemoteObject), Charles shows me that the request looks like this:
unexpected result http://img.skitch.com/20100406-cjawastycagp1x2chbe76k2suu.png
But it seems wrong that my serialized object is leaking out into the rest of the request.
So, what am I doing wrong? Is there some part of the documentation I've missed?
You code seems fine, however you should serialize using the proper methods (writeUTF for strings, writeInt for int etc). Anyway Charles seems to not work properly with objects implementing IExternalizable (I'm using version 3.4.1), so you should not rely on what it is showing.
Not directly related to your question - do you really need to use IExternalizable? You are going to lose some benefits related to AMF compression algorithm (unless you are not going to implement all this things in your writeExternal method).